pax_global_header00006660000000000000000000000064151317146720014521gustar00rootroot0000000000000052 comment=f104efea40d66180a4c57f092ab5836d2f9dd084 metkit-1.16.0/000077500000000000000000000000001513171467200131035ustar00rootroot00000000000000metkit-1.16.0/.clang-format000066400000000000000000000054401513171467200154610ustar00rootroot00000000000000Language: Cpp AccessModifierOffset: -4 AlignAfterOpenBracket: Align AlignConsecutiveAssignments: true AlignConsecutiveDeclarations: false AlignEscapedNewlines: Left AlignOperands: true AlignTrailingComments: true AllowAllParametersOfDeclarationOnNextLine: true AllowShortBlocksOnASingleLine: true AllowShortCaseLabelsOnASingleLine: false AllowShortFunctionsOnASingleLine: Inline AllowShortIfStatementsOnASingleLine: false AllowShortLoopsOnASingleLine: false AllowShortEnumsOnASingleLine: false AlwaysBreakAfterDefinitionReturnType: None AlwaysBreakBeforeMultilineStrings: true AlwaysBreakTemplateDeclarations: true BinPackArguments: true BinPackParameters: true BraceWrapping: AfterClass: false AfterControlStatement: false AfterEnum: false AfterFunction: false AfterNamespace: false AfterObjCDeclaration: false AfterStruct: false AfterUnion: false BeforeCatch: true BeforeElse: true IndentBraces: false SplitEmptyFunction: true SplitEmptyRecord: true SplitEmptyNamespace: true BreakAfterReturnType: Automatic BreakBeforeBinaryOperators: None BreakBeforeBraces: Custom BreakBeforeInheritanceComma: false BreakBeforeTernaryOperators: true BreakConstructorInitializersBeforeComma: false BreakConstructorInitializers: AfterColon BreakAfterJavaFieldAnnotations: false BreakStringLiterals: true ColumnLimit: 120 CommentPragmas: '^ IWYU pragma:' CompactNamespaces: false ConstructorInitializerAllOnOneLineOrOnePerLine: true ConstructorInitializerIndentWidth: 4 ContinuationIndentWidth: 4 Cpp11BracedListStyle: true DerivePointerAlignment: false DisableFormat: false ExperimentalAutoDetectBinPacking: false EmptyLineBeforeAccessModifier: Always EmptyLineAfterAccessModifier: Always FixNamespaceComments: true ForEachMacros: - foreach - Q_FOREACH - BOOST_FOREACH IncludeCategories: - Regex: '^<.*\.h>' Priority: 1 - Regex: '^<.*' Priority: 2 - Regex: '.*' Priority: 3 IncludeIsMainRegex: '([-_](test|unittest))?$' IndentCaseLabels: true IndentWidth: 4 IndentWrappedFunctionNames: false KeepEmptyLinesAtTheStartOfBlocks: true MacroBlockBegin: '' MacroBlockEnd: '' MaxEmptyLinesToKeep: 2 NamespaceIndentation: None PenaltyBreakAssignment: 2 PenaltyBreakBeforeFirstCallParameter: 1 PenaltyBreakComment: 300 PenaltyBreakFirstLessLess: 120 PenaltyBreakString: 1000 PenaltyExcessCharacter: 1000000 PenaltyReturnTypeOnItsOwnLine: 200 PointerAlignment: Left ReflowComments: true SortIncludes: true SortUsingDeclarations: true SpaceAfterCStyleCast: false SpaceAfterTemplateKeyword: true SpaceBeforeAssignmentOperators: true SpaceBeforeParens: ControlStatements SpaceInEmptyParentheses: false SpacesBeforeTrailingComments: 2 SpacesInAngles: false SpacesInContainerLiterals: true SpacesInCStyleCastParentheses: false SpacesInParentheses: false SpacesInSquareBrackets: false Standard: Auto TabWidth: 4 UseTab: Never metkit-1.16.0/.git-blame-ignore-revs000066400000000000000000000007001513171467200172000ustar00rootroot00000000000000# The following refs can be ignored by git blame if 'git blame' is called with # --ignore-revs-file .git-blame-ignore-revs # Alternatively configure git to always ignore refs stored in this file by # calling: # git config blame.ignoreRevsFile .git-blame-ignore-revs # Or extend your git config manually with # [blame] # ignoreRevsFile = .git-blame-ignore-revs # Reformatted codebase with clang-format caa877e4812ef00c792326f8d71683f95422c33f metkit-1.16.0/.github/000077500000000000000000000000001513171467200144435ustar00rootroot00000000000000metkit-1.16.0/.github/ci-config.yml000066400000000000000000000002321513171467200170210ustar00rootroot00000000000000dependencies: | ecmwf/ecbuild MathisRosenhauer/libaec@refs/tags/v1.1.3 ecmwf/eccodes ecmwf/eckit dependency_branch: develop parallelism_factor: 8 metkit-1.16.0/.github/ci-hpc-config.yml000066400000000000000000000004311513171467200175720ustar00rootroot00000000000000build: modules: - ninja dependencies: - ecmwf/ecbuild@develop - ecmwf/eccodes@develop - ecmwf/eckit@develop parallel: 64 env: - ECCODES_SAMPLES_PATH=$ECCODES_DIR/share/eccodes/samples - ECCODES_DEFINITION_PATH=$ECCODES_DIR/share/eccodes/definitions metkit-1.16.0/.github/workflows/000077500000000000000000000000001513171467200165005ustar00rootroot00000000000000metkit-1.16.0/.github/workflows/build-wheel-wrapper.yml000066400000000000000000000014031513171467200231000ustar00rootroot00000000000000# (C) Copyright 2024- ECMWF. # # This software is licensed under the terms of the Apache Licence Version 2.0 # which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. # In applying this licence, ECMWF does not waive the privileges and immunities # granted to it by virtue of its status as an intergovernmental organisation # nor does it submit to any jurisdiction. name: Build Python Wrapper Wheel on: # Trigger the workflow manually workflow_dispatch: ~ # Allow to be called from another workflow -- eg `cd.yml` workflow_call: ~ jobs: python-wrapper-wheel: name: Python Wrapper Wheel uses: ecmwf/reusable-workflows/.github/workflows/python-wrapper-wheel.yml@main with: wheel_directory: python/metkitlib secrets: inherit metkit-1.16.0/.github/workflows/cd.yml000066400000000000000000000006041513171467200176110ustar00rootroot00000000000000name: cd on: push: tags: - '**' jobs: deploy: uses: ecmwf/reusable-workflows/.github/workflows/create-package.yml@v2 secrets: inherit wheel-wrapper: uses: ./.github/workflows/build-wheel-wrapper.yml secrets: inherit wheel-python: uses: ecmwf/reusable-workflows/.github/workflows/cd-pypi.yml@v2 secrets: inherit needs: - wheel-wrapper metkit-1.16.0/.github/workflows/check-release-version.yml000066400000000000000000000003071513171467200234010ustar00rootroot00000000000000name: Check VERSION file on: push: branches: - "release/**" - "hotfix/**" jobs: check_version: uses: ecmwf/reusable-workflows/.github/workflows/check-release-version.yml@v2 metkit-1.16.0/.github/workflows/ci.yml000066400000000000000000000064531513171467200176260ustar00rootroot00000000000000name: ci on: # Trigger the workflow on push to master or develop, except tag creation push: branches: - 'master' - 'develop' tags-ignore: - '**' # Trigger the workflow on pull request pull_request: ~ # Trigger the workflow manually workflow_dispatch: ~ # Trigger after public PR approved for CI pull_request_target: types: [labeled] jobs: # Run CI including downstream packages on self-hosted runners downstream-ci: name: downstream-ci if: ${{ !github.event.pull_request.head.repo.fork && github.event.action != 'labeled' || github.event.label.name == 'approved-for-ci' }} uses: ecmwf/downstream-ci/.github/workflows/downstream-ci.yml@main with: metkit: ecmwf/metkit@${{ github.event.pull_request.head.sha || github.sha }} codecov_upload: true clang_format: true secrets: inherit # Run CI of private downstream packages on self-hosted runners private-downstream-ci: name: private-downstream-ci needs: [downstream-ci] if: ${{ (success() || failure()) && (!github.event.pull_request.head.repo.fork && github.event.action != 'labeled' || github.event.label.name == 'approved-for-ci') }} runs-on: ubuntu-latest permissions: pull-requests: write steps: - name: Dispatch private downstream CI uses: ecmwf/dispatch-private-downstream-ci@v1 with: token: ${{ secrets.GH_REPO_READ_TOKEN }} owner: ecmwf repository: private-downstream-ci event_type: downstream-ci payload: '{"metkit": "ecmwf/metkit@${{ github.event.pull_request.head.sha || github.sha }}"}' # Build downstream packages on HPC downstream-ci-hpc: name: downstream-ci-hpc if: ${{ !github.event.pull_request.head.repo.fork && github.event.action != 'labeled' || github.event.label.name == 'approved-for-ci' }} uses: ecmwf/downstream-ci/.github/workflows/downstream-ci-hpc.yml@main with: metkit: ecmwf/metkit@${{ github.event.pull_request.head.sha || github.sha }} secrets: inherit # Run CI of private downstream packages on HPC private-downstream-ci-hpc: name: private-downstream-ci-hpc needs: [downstream-ci-hpc] if: ${{ (success() || failure()) && (!github.event.pull_request.head.repo.fork && github.event.action != 'labeled' || github.event.label.name == 'approved-for-ci') }} runs-on: ubuntu-latest permissions: pull-requests: write steps: - name: Dispatch private downstream CI uses: ecmwf/dispatch-private-downstream-ci@v1 with: token: ${{ secrets.GH_REPO_READ_TOKEN }} owner: ecmwf repository: private-downstream-ci event_type: downstream-ci-hpc payload: '{"metkit": "ecmwf/metkit@${{ github.event.pull_request.head.sha || github.sha }}"}' notify: runs-on: ubuntu-latest needs: - downstream-ci - private-downstream-ci - downstream-ci-hpc - private-downstream-ci-hpc if: ${{ always() && !github.event.pull_request.head.repo.fork && (github.event.action != 'labeled' || github.event.label.name == 'approved-for-ci') }} steps: - name: Trigger Teams notification uses: ecmwf/notify-teams@v1 with: incoming_webhook: ${{ secrets.MS_TEAMS_INCOMING_WEBHOOK }} needs_context: ${{ toJSON(needs) }} metkit-1.16.0/.github/workflows/label-public-pr.yml000066400000000000000000000003431513171467200221750ustar00rootroot00000000000000# Manage labels of pull requests that originate from forks name: label-public-pr on: pull_request_target: types: [opened, synchronize] jobs: label: uses: ecmwf/reusable-workflows/.github/workflows/label-pr.yml@v2 metkit-1.16.0/.github/workflows/notify-issues.yml000066400000000000000000000004211513171467200220410ustar00rootroot00000000000000name: Notify Issues on: issues: types: [opened, reopened] jobs: notify: runs-on: ubuntu-latest steps: - name: Notify Issues uses: ecmwf/notify-teams-issue@v1 with: incoming_webhook: ${{ secrets.MS_TEAMS_INCOMING_WEBHOOK }} metkit-1.16.0/.github/workflows/notify-pull-request.yml000066400000000000000000000004471513171467200232000ustar00rootroot00000000000000name: Notify Pull Request on: pull_request_target: types: [opened, reopened] jobs: notify: runs-on: ubuntu-latest steps: - name: Notify Pull Request uses: ecmwf/notify-teams-pr@v1 with: incoming_webhook: ${{ secrets.MS_TEAMS_INCOMING_WEBHOOK }} metkit-1.16.0/.github/workflows/sync.yml000066400000000000000000000011511513171467200201750ustar00rootroot00000000000000name: sync # Controls when the workflow will run on: # Trigger the workflow on all pushes push: branches: - '**' tags: - '**' # Trigger the workflow when a branch or tag is deleted delete: ~ jobs: # Calls a reusable CI workflow to sync the current with a remote repository. # It will correctly handle addition of any new and removal of existing Git objects. sync: name: sync uses: ecmwf/reusable-workflows/.github/workflows/sync.yml@v2 secrets: target_repository: ecsdk/metkit target_username: ClonedDuck target_token: ${{ secrets.BITBUCKET_PAT }} metkit-1.16.0/.gitignore000066400000000000000000000003411513171467200150710ustar00rootroot00000000000000.atom-build.yaml .tags* CMakeLists.txt.user* *.autosave doc/html doc/latex *.sublime-workspace .*.sw* .*un~ *.ccls-cache *.py[cod] *.swp **/__pycache__ .vscode *.egg-info .pytest_cache *.prof *.idx .mypy_cache build/ Testing/metkit-1.16.0/.vscode/000077500000000000000000000000001513171467200144445ustar00rootroot00000000000000metkit-1.16.0/.vscode/launch.json000066400000000000000000000131771513171467200166220ustar00rootroot00000000000000{ // Use IntelliSense to learn about possible attributes. // Hover to view descriptions of existing attributes. // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 "version": "0.2.0", "configurations": [ { "name": "Python: Current File", "type": "python", "request": "launch", "program": "${file}", "console": "integratedTerminal", "justMyCode": true }, { "name": "make params MARS yaml (deprecated method)", "type": "python", "request": "launch", "program": "${env:HOME}/git/metkit/share/metkit/make-params-yaml.py", "console": "integratedTerminal", "justMyCode": false, "env": { "ECFLOW_DIR": "/usr/local/apps/ecflow/5.8.1" // "${env:ECFLOW_DIR}" }, "args": [""], "cwd":"${env:HOME}/git/metkit/share/metkit/" }, { "name": "make paramIds yaml - 0001", "type": "python", "request": "launch", "program": "${env:HOME}/git/metkit/share/metkit/make-paramids-yaml.py", "console": "integratedTerminal", "justMyCode": false, "env": { "ECFLOW_DIR": "/usr/local/apps/ecflow/5.8.1" // "${env:ECFLOW_DIR}" }, "args": [""], "cwd":"${env:HOME}/git/metkit/share/metkit/" }, { "name": "make paramIds yaml - 0078", "type": "python", "request": "launch", "program": "${env:HOME}/git/metkit/share/metkit/make-paramids-yaml-esuite.py", "console": "integratedTerminal", "justMyCode": false, "env": { "ECFLOW_DIR": "/usr/local/apps/ecflow/5.8.1" // "${env:ECFLOW_DIR}" }, "args": [""], "cwd":"${env:HOME}/git/metkit/share/metkit/" }, { "name": "make params FDB yaml - 0001", "type": "python", "request": "launch", "program": "${env:HOME}/git/metkit/share/metkit/make-params-yaml-from-fields-catalogue.py", "console": "integratedTerminal", "justMyCode": false, "env": { "ECFLOW_DIR": "/usr/local/apps/ecflow/5.8.1", // "${env:ECFLOW_DIR}" "PRODUCT_CATALOGUE_HOST": "bol-db-products-prod-01", "PRODUCT_CATALOGUE_DB": "products", "PRODUCT_CATALOGUE_USER": "ecmwf_ro", "PRODUCT_CATALOGUE_PASSWORD": "ecmwf_ro", "PRODUCT_CATALOGUE_PORT": "5432", "VALIDATION_SERVICE_HOST": "https://products.ecmwf.int/requirements/" }, "args": [""], "cwd":"${env:HOME}/git/metkit/share/metkit/" }, { "name": "make params FDB yaml - 0078 - preprod", "type": "python", "request": "launch", "program": "${env:HOME}/git/metkit/share/metkit/make-params-yaml-from-fields-catalogue.py", "console": "integratedTerminal", "justMyCode": false, "env": { "ECFLOW_DIR": "/usr/local/apps/ecflow/5.8.1", // "${env:ECFLOW_DIR}" "PRODUCT_CATALOGUE_HOST": "k8s-bol-webapps-test-worker-016", "PRODUCT_CATALOGUE_DB": "products", "PRODUCT_CATALOGUE_USER": "products", "PRODUCT_CATALOGUE_PASSWORD": "products", "PRODUCT_CATALOGUE_PORT": "30544", "VALIDATION_SERVICE_HOST": "https://products-test.ecmwf.int/esuite/requirements/" }, "args": [""], "cwd":"${env:HOME}/git/metkit/share/metkit/" }, { "name": "make params FDB yaml - 0078 - prod", "type": "python", "request": "launch", "program": "${env:HOME}/git/metkit/share/metkit/make-params-yaml-from-fields-catalogue.py", "console": "integratedTerminal", "justMyCode": false, "env": { "ECFLOW_DIR": "/usr/local/apps/ecflow/5.8.1", // "${env:ECFLOW_DIR}" "PRODUCT_CATALOGUE_HOST": "k8s-bol-webapps-prod-worker-012", "PRODUCT_CATALOGUE_DB": "products", "PRODUCT_CATALOGUE_USER": "products", "PRODUCT_CATALOGUE_PASSWORD": "products", "PRODUCT_CATALOGUE_PORT": "30545", "VALIDATION_SERVICE_HOST": "https://products.ecmwf.int/esuite/requirements/" }, "args": [""], "cwd":"${env:HOME}/git/metkit/share/metkit/" }, { "name": "make fields DB yaml - 0001", "type": "python", "request": "launch", "program": "${env:HOME}/git/metkit/share/metkit/fieldsdb.py", "console": "integratedTerminal", "justMyCode": false, "env": { "ECFLOW_DIR": "/usr/local/apps/ecflow/5.8.1", // "${env:ECFLOW_DIR}" }, "args": [""], "cwd":"${env:HOME}/git/metkit/share/metkit/" }, { "name": "make fields DB yaml - 0078", "type": "python", "request": "launch", "program": "${env:HOME}/git/metkit/share/metkit/fieldsdb-esuite.py", "console": "integratedTerminal", "justMyCode": false, "env": { "ECFLOW_DIR": "/usr/local/apps/ecflow/5.8.1", // "${env:ECFLOW_DIR}" }, "args": [""], "cwd":"${env:HOME}/git/metkit/share/metkit/" }, ] } metkit-1.16.0/AUTHORS000066400000000000000000000004001513171467200141450ustar00rootroot00000000000000metkit authors ============= The main development of metkit is done at the European Centre for Medium-Range Weather Forecasts (ECMWF - http://www.ecmwf.int ) Current developers ================== Baudouin Raoult Tiago Quintino Simon Smart Matthias Zink metkit-1.16.0/CMakeLists.txt000066400000000000000000000060161513171467200156460ustar00rootroot00000000000000# (C) Copyright 2011- ECMWF. # # This software is licensed under the terms of the Apache Licence Version 2.0 # which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. # In applying this licence, ECMWF does not waive the privileges and immunities # granted to it by virtue of its status as an intergovernmental organisation nor # does it submit to any jurisdiction. ######################################################################################################################## cmake_minimum_required( VERSION 3.18 FATAL_ERROR ) find_package( ecbuild 3.12 REQUIRED HINTS ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/../ecbuild) project( metkit LANGUAGES CXX C ) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) ######################################################################################################################## ### dependencies and options if(NOT METKIT_CONFIGS_BRANCH) set(METKIT_CONFIGS_BRANCH chk) endif() ecbuild_add_option( FEATURE BUILD_TOOLS DEFAULT ON DESCRIPTION "Build the command line tools" ) ecbuild_add_option( FEATURE EXPERIMENTAL DEFAULT OFF DESCRIPTION "Experimental features" ) # GRIB support ecbuild_add_option( FEATURE GRIB DEFAULT ON DESCRIPTION "Add support for GRIB format" REQUIRED_PACKAGES "NAME eccodes VERSION 2.27" ) # BUFR support ecbuild_add_option( FEATURE BUFR DEFAULT ON DESCRIPTION "Add support for BUFR format" REQUIRED_PACKAGES "NAME eccodes VERSION 2.27" ) # netcdf support ecbuild_add_option( FEATURE NETCDF DEFAULT ON DESCRIPTION "Support for NetCDF data" REQUIRED_PACKAGES NetCDF ) # ODB support ecbuild_add_option( FEATURE ODB DEFAULT ON DESCRIPTION "Add support for ODB data" REQUIRED_PACKAGES "NAME odc VERSION 1.0" ) # METKIT config files support ecbuild_add_option( FEATURE METKIT_CONFIG DEFAULT ON DESCRIPTION "Install metkit configuration files" ) # Temporary ecbuild_add_option( FEATURE FAIL_ON_CCSDS DESCRIPTION "Fail on CCSDS" DEFAULT OFF ) # eckit set( PERSISTENT_NAMESPACE "eckit" CACHE INTERNAL "" ) # needed for generating .b files for persistent support ecbuild_find_package( NAME eckit VERSION 1.32 REQUIRED ) ############################################################################################ # sources include(cmake/compiler_warnings.cmake) # optionally handle compiler specific warnings add_subdirectory( src ) add_subdirectory( share ) add_subdirectory( tests ) ############################################################################################ # finalize ecbuild_pkgconfig( NAME metkit DESCRIPTION "ECMWF Meteorological toolkit" LIBRARIES metkit ) ecbuild_install_project( NAME ${PROJECT_NAME} ) ecbuild_print_summary() metkit-1.16.0/LICENSE000066400000000000000000000247771513171467200141310ustar00rootroot00000000000000 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS Copyright 1996- ECMWF Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. metkit-1.16.0/NOTICE000066400000000000000000000006351513171467200140130ustar00rootroot00000000000000metkit ====== Copyright 1996- ECMWF This product is developed by the Development Section, European Centre for Medium-Range Weather Forecasts (ECMWF) - http://www.ecmwf.int Below is a list of software packages which are used inside: - No external package in currently included Please also read the cmake/NOTICE file bundled in the distribution packages, which lists the included third-party CMake macros. metkit-1.16.0/README.md000066400000000000000000000043071513171467200143660ustar00rootroot00000000000000 [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://github.com/ecmwf/metkit/blob/develop/LICENSE) [![Static Badge](https://github.com/ecmwf/codex/raw/refs/heads/main/Project%20Maturity/graduated_badge.svg)](https://github.com/ecmwf/codex/raw/refs/heads/main/Project%20Maturity#graduated)) > \[!IMPORTANT\] > This software is **Graduated** and subject to ECMWF's guidelines on [Software Maturity](https://github.com/ecmwf/codex/raw/refs/heads/main/Project%20Maturity). # metkit ## Requirements Runtime dependencies: - eckit -- http://github.com/ecmwf/eckit Build dependencies: - CMake --- For use and installation see http://www.cmake.org/ - ecbuild --- ECMWF library of CMake macros () ## Installation metkit employs an out-of-source build/install based on CMake. Make sure ecbuild is installed and the ecbuild executable script is found ( `which ecbuild` ). Now proceed with installation as follows: ```bash # Environment --- Edit as needed srcdir=$(pwd) builddir=build installdir=$HOME/local # 1. Create the build directory: mkdir $builddir cd $builddir # 2. Run CMake ecbuild --prefix=$installdir -- -DECKIT_PATH= $srcdir # 3. Compile / Install make -j10 make install ``` ## Release Config files should be updated before releasing a new version. Please refer to the documentation available on [Confluence](https://confluence.ecmwf.int/display/METK/MetKit+configuration) ## License Copyright 2021 European Centre for Medium-Range Weather Forecasts (ECMWF) Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at > http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. In applying this licence, ECMWF does not waive the privileges and immunities granted to it by virtue of its status as an intergovernmental organisation nor does it submit to any jurisdiction.metkit-1.16.0/VERSION000066400000000000000000000000061513171467200141470ustar00rootroot000000000000001.16.0metkit-1.16.0/bamboo/000077500000000000000000000000001513171467200143425ustar00rootroot00000000000000metkit-1.16.0/bamboo/CLANG-env.sh000066400000000000000000000006531513171467200163140ustar00rootroot00000000000000#!/bin/bash [[ $(uname) == "Darwin" ]] && return # no module environment on the Mac # initialise module environment if it is not if [[ ! $(command -v module > /dev/null 2>&1) ]]; then . /usr/local/apps/module/init/bash fi module unload grib_api module unload eccodes module unload emos module unload fftw module unload libemos module unload metview module unload netcdf4 module load cmake/3.16.5 module switch gnu clang metkit-1.16.0/bamboo/CMakeLists.txt000066400000000000000000000002541513171467200171030ustar00rootroot00000000000000file( GLOB_RECURSE bamboo_files RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "*" ) ecbuild_add_resources( TARGET ${PROJECT_NAME}_bamboo SOURCES_DONT_PACK ${bamboo_files} ) metkit-1.16.0/bamboo/GCC-env.sh000066400000000000000000000006221513171467200160600ustar00rootroot00000000000000#!/bin/bash [[ $(uname) == "Darwin" ]] && return # no module environment on the Mac # initialise module environment if it is not if [[ ! $(command -v module > /dev/null 2>&1) ]]; then . /usr/local/apps/module/init/bash fi module unload grib_api module unload eccodes module unload emos module unload fftw module unload libemos module unload metview module unload netcdf4 module load cmake/3.16.5 metkit-1.16.0/bamboo/INTEL-env.sh000066400000000000000000000006621513171467200163430ustar00rootroot00000000000000#!/bin/bash [[ $(uname) == "Darwin" ]] && return # no module environment on the Mac # initialise module environment if it is not if [[ ! $(command -v module > /dev/null 2>&1) ]]; then . /usr/local/apps/module/init/bash fi module unload grib_api module unload eccodes module unload emos module unload fftw module unload libemos module unload metview module unload netcdf4 module load cmake/3.16.5 module switch gnu intel/17.0.3 metkit-1.16.0/bamboo/MACOSX-env.sh000066400000000000000000000000751513171467200164600ustar00rootroot00000000000000export PATH=$HOME/Applications/CMake.app/Contents/bin:$PATH metkit-1.16.0/bamboo/env.sh000066400000000000000000000000761513171467200154710ustar00rootroot00000000000000#!/usr/bin/env bash # export VAR=VALUE # ctest_parallel="no" metkit-1.16.0/cmake/000077500000000000000000000000001513171467200141635ustar00rootroot00000000000000metkit-1.16.0/cmake/compiler_warnings.cmake000066400000000000000000000007471513171467200207170ustar00rootroot00000000000000ecbuild_add_option( FEATURE WARNINGS DEFAULT ON DESCRIPTION "Add warnings to compiler" ) # activate warnings, ecbuild macros check the compiler recognises the options if(HAVE_WARNINGS) ecbuild_add_cxx_flags("-Wall" NO_FAIL) ecbuild_add_cxx_flags("-Wextra" NO_FAIL) ecbuild_add_cxx_flags("-Wno-unused-parameter" NO_FAIL) ecbuild_add_cxx_flags("-Wno-unused-variable" NO_FAIL) ecbuild_add_cxx_flags("-Wno-sign-compare" NO_FAIL) endif() metkit-1.16.0/metkit-import.cmake.in000066400000000000000000000006501513171467200173200ustar00rootroot00000000000000set( metkit_HAVE_GRIB @metkit_HAVE_GRIB@ ) set( metkit_HAVE_ODB @metkit_HAVE_ODB@ ) include( CMakeFindDependencyMacro ) find_dependency( eckit HINTS ${CMAKE_CURRENT_LIST_DIR}/../eckit @eckit_DIR@ ) if( metkit_HAVE_GRIB ) find_dependency( eccodes HINTS ${CMAKE_CURRENT_LIST_DIR}/../eccodes @metkit_DIR@ ) endif() if( metkit_HAVE_ODB ) find_dependency( odc HINTS ${CMAKE_CURRENT_LIST_DIR}/../odc @odc_DIR@ ) endif() metkit-1.16.0/metkit.code-workspace000066400000000000000000000000531513171467200172260ustar00rootroot00000000000000{ "folders": [ { "path": "." } ] }metkit-1.16.0/pyproject.toml000066400000000000000000000016501513171467200160210ustar00rootroot00000000000000# pytest [tool.pytest.ini_options] minversion = "6.0" addopts = "-vv -s" testpaths = [ "pymetkit/tests" ] # pyproject.toml [build-system] requires = ["setuptools", "wheel", "cffi"] build-backend = "setuptools.build_meta" [project] name = "pymetkit" description = "Python interface for metkit" dynamic = ["version"] authors = [ { name = "European Centre for Medium-Range Weather Forecasts (ECMWF)", email = "software.support@ecmwf.int" }, ] license = { text = "Apache License Version 2.0" } requires-python = ">=3.10" dependencies = [ "cffi", "metkitlib", "findlibs" ] [tool.setuptools.dynamic] version = { file = ["VERSION"] } [tool.setuptools] packages = ["pymetkit"] package-dir = { "pymetkit" = "./python/pymetkit/src/pymetkit" } include-package-data = true zip-safe = false [tool.setuptools.package-data] "pymetkit" = [ "VERSION", "metkit_c.h" ] [project.optional-dependencies] tests = ["pytest"] metkit-1.16.0/python/000077500000000000000000000000001513171467200144245ustar00rootroot00000000000000metkit-1.16.0/python/metkitlib/000077500000000000000000000000001513171467200164105ustar00rootroot00000000000000metkit-1.16.0/python/metkitlib/buildconfig000066400000000000000000000015761513171467200206310ustar00rootroot00000000000000# (C) Copyright 2024- ECMWF. # # This software is licensed under the terms of the Apache Licence Version 2.0 # which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. # In applying this licence, ECMWF does not waive the privileges and immunities # granted to it by virtue of its status as an intergovernmental organisation # nor does it submit to any jurisdiction. # to be source'd by wheelmaker's compile.sh *and* wheel-linux.sh # NOTE replace the whole thing with pyproject.toml? Less powerful, and quaint to use for sourcing ecbuild invocation # TODO we duplicate information -- pyproject.toml's `name` and `packages` are derivable from $NAME and must stay consistent NAME="metkit" CMAKE_PARAMS="-Deckit_ROOT=/tmp/metkit/prereqs/eckitlib -Deccodes_ROOT=/tmp/metkit/prereqs/eccodeslib -DENABLE_GRIB=1" PYPROJECT_DIR="python/metkitlib" DEPENDENCIES='["eckitlib", "eccodeslib"]' metkit-1.16.0/python/metkitlib/setup.cfg000066400000000000000000000002151513171467200202270ustar00rootroot00000000000000[metadata] description = "metkitlib" long_description = file: README.md long_description_content_type = text/markdown author = file: AUTHORS metkit-1.16.0/python/metkitlib/setup.py000066400000000000000000000000621513171467200201200ustar00rootroot00000000000000from setup_utils import plain_setup plain_setup() metkit-1.16.0/python/pymetkit/000077500000000000000000000000001513171467200162725ustar00rootroot00000000000000metkit-1.16.0/python/pymetkit/README.md000066400000000000000000000021651513171467200175550ustar00rootroot00000000000000# pymetkit This repository contains an Python interface to the MetKit library for parsing MARS requests. ## Example The function for parsing a MARS request is `metkit.parse_mars_request` which accepts a string or file-like object as inputs. A list of `metkit.mars.Request` instances are returned, which is a dictionary containing the keys and values in the MARS request and the attribute `verb` for the verb in the MARS request. ### From String ``` from metkit import parse_mars_request request_str = "retrieve,class=od,date=20240124,time=12,param=129,step=12,target=test.grib" requests = parse_mars_request(requests) print(requests[0]) # verb: retrieve, request: {'class': ['od'], 'date': ['20240124'], 'time': ['1200'], 'param': ['129'], 'step': ['12'], 'target': ['test.grib'], 'domain': ['g'], 'expver': ['0001'], 'levelist': ['1000', '850', '700', '500', '400', '300'], 'levtype': ['pl'], 'stream': ['oper'], 'type': ['an']} ``` ### From File If the MARS request is contained inside a file, e.g. test_requests.txt: ``` from metkit import parse_mars_request requests = parse_mars_request(open("test_requests.txt", "r")) ``` metkit-1.16.0/python/pymetkit/src/000077500000000000000000000000001513171467200170615ustar00rootroot00000000000000metkit-1.16.0/python/pymetkit/src/pymetkit/000077500000000000000000000000001513171467200207275ustar00rootroot00000000000000metkit-1.16.0/python/pymetkit/src/pymetkit/__init__.py000066400000000000000000000000301513171467200230310ustar00rootroot00000000000000from .pymetkit import * metkit-1.16.0/python/pymetkit/src/pymetkit/_version.py000066400000000000000000000002011513171467200231160ustar00rootroot00000000000000from pathlib import Path from .pymetkit import * import importlib.metadata __version__ = importlib.metadata.version("pymetkit") metkit-1.16.0/python/pymetkit/src/pymetkit/metkit_c.h000066400000000000000000000061171513171467200227040ustar00rootroot00000000000000 struct metkit_marsrequest_t; typedef struct metkit_marsrequest_t metkit_marsrequest_t; struct metkit_requestiterator_t; typedef struct metkit_requestiterator_t metkit_requestiterator_t; struct metkit_paramiterator_t; typedef struct metkit_paramiterator_t metkit_paramiterator_t; typedef enum metkit_error_values_t { METKIT_SUCCESS = 0, /* Operation succeded. */ METKIT_ERROR = 1, /* Operation failed. */ METKIT_ERROR_UNKNOWN = 2, /* Failed with an unknown error. */ METKIT_ERROR_USER = 3, /* Failed with an user error. */ METKIT_ERROR_ASSERT = 4 /* Failed with an assert() */ } metkit_error_t; typedef enum metkit_iterator_status_t { METKIT_ITERATOR_SUCCESS = 0, /* Operation succeded. */ METKIT_ITERATOR_COMPLETE = 1, /* All elements have been returned */ METKIT_ITERATOR_ERROR = 2 /* Operation failed. */ } metkit_iterator_status_t; const char* metkit_get_error_string(enum metkit_error_values_t err); const char* metkit_version(); const char* metkit_git_sha1(); metkit_error_t metkit_initialise(); metkit_error_t metkit_parse_marsrequests(const char* str, metkit_requestiterator_t** requests, bool strict); metkit_error_t metkit_marsrequest_new(metkit_marsrequest_t** request); metkit_error_t metkit_marsrequest_delete(const metkit_marsrequest_t* request); metkit_error_t metkit_marsrequest_set(metkit_marsrequest_t* request, const char* param, const char* values[], int numValues); metkit_error_t metkit_marsrequest_set_one(metkit_marsrequest_t* request, const char* param, const char* value); metkit_error_t metkit_marsrequest_set_verb(metkit_marsrequest_t* request, const char* verb); metkit_error_t metkit_marsrequest_verb(const metkit_marsrequest_t* request, const char** verb); metkit_error_t metkit_marsrequest_has_param(const metkit_marsrequest_t* request, const char* param, bool* has); metkit_error_t metkit_marsrequest_params(const metkit_marsrequest_t* request, metkit_paramiterator_t** params); metkit_error_t metkit_marsrequest_count_values(const metkit_marsrequest_t* request, const char* param, size_t* count); metkit_error_t metkit_marsrequest_value(const metkit_marsrequest_t* request, const char* param, int index, const char** value); metkit_error_t metkit_marsrequest_expand(const metkit_marsrequest_t* request, bool inherit, bool strict, metkit_marsrequest_t* expandedRequest); metkit_error_t metkit_marsrequest_merge(metkit_marsrequest_t* request, const metkit_marsrequest_t* otherRequest); metkit_error_t metkit_requestiterator_delete(const metkit_requestiterator_t* it); metkit_iterator_status_t metkit_requestiterator_next(metkit_requestiterator_t* it); metkit_iterator_status_t metkit_requestiterator_current(metkit_requestiterator_t* it, metkit_marsrequest_t* request); metkit_error_t metkit_paramiterator_delete(const metkit_paramiterator_t* it); metkit_iterator_status_t metkit_paramiterator_next(metkit_paramiterator_t* it); metkit_iterator_status_t metkit_paramiterator_current(const metkit_paramiterator_t* it, const char** param); metkit-1.16.0/python/pymetkit/src/pymetkit/pymetkit.py000066400000000000000000000233551513171467200231570ustar00rootroot00000000000000import os from cffi import FFI import findlibs from typing import IO, Iterator import warnings from ._version import __version__ ffi = FFI() def ffi_encode(data) -> bytes: if isinstance(data, bytes): return data if not isinstance(data, str): data = str(data) return data.encode(encoding="utf-8", errors="surrogateescape") def ffi_decode(data: FFI.CData) -> str: buf = ffi.string(data) if isinstance(buf, str): return buf else: return buf.decode(encoding="utf-8", errors="surrogateescape") class MarsRequest: def __init__(self, verb: str | None = None, **kwargs): """ Create MetKit MarsRequest object. Parameters and values in the request can be specified through kwargs, noting that reserved words in Python must be suffixed with "_" e.g. "class_" """ crequest = ffi.new("metkit_marsrequest_t **") lib.metkit_marsrequest_new(crequest) self.__request = ffi.gc(crequest[0], lib.metkit_marsrequest_delete) if verb is not None: lib.metkit_marsrequest_set_verb(self.__request, ffi_encode(verb)) for param, values in kwargs.items(): self[param.rstrip("_")] = values def ctype(self) -> FFI.CData: return self.__request def verb(self) -> str: cverb = ffi.new("const char **") lib.metkit_marsrequest_verb(self.__request, cverb) return ffi_decode(cverb[0]) def expand(self, inherit: bool = True, strict: bool = False) -> "MarsRequest": """ Return expanded request Params ------ inherit: bool, if True, populates expanded request with default values strict: bool, if True, raise error instead of warning for invalid values Returns ------- Request, resulting from expansion """ expanded_request = MarsRequest() lib.metkit_marsrequest_expand( self.__request, inherit, strict, expanded_request.ctype() ) return expanded_request def validate(self): """ Check if request is valid against MARS language definition. Does not inherit missing parameters. Raises ------ Exception if request is incompatible with MARS language definition """ self.expand(False, True) def keys(self) -> Iterator[str]: """ Get iterator over parameters in request Returns ------- Iterator over parameter names """ it_c = ffi.new("metkit_paramiterator_t **") lib.metkit_marsrequest_params(self.__request, it_c) it = ffi.gc(it_c[0], lib.metkit_paramiterator_delete) while lib.metkit_paramiterator_next(it) == lib.METKIT_ITERATOR_SUCCESS: cparam = ffi.new("const char **") lib.metkit_paramiterator_current(it, cparam) param = ffi_decode(cparam[0]) yield param def num_values(self, param: str) -> int: """ Number of values for parameter Params ------ param: parameter name Returns ------- int """ cparam = ffi_encode(param) count = ffi.new("size_t *", 0) lib.metkit_marsrequest_count_values(self.__request, cparam, count) return count[0] def merge(self, other: "MarsRequest") -> "MarsRequest": """ Merge the values in another request with existing request and returns result as a new Request object. Does not modify inputs to merge. Both input requests must contain the same values and the resulting request object must be compatible with MARS language definition Params ------ other: Request, request to merge with self Returns ------- Request, containing the result of the merge Raises ------ ValueError if parameters in the two requests do not match MetKitException if resulting request is not compatible with MARS language definition """ if set(self.keys()) != set(other.keys()): raise ValueError("Can not merge requests with different parameters.") res = MarsRequest(self.verb(), **{k: v for k, v in self}) lib.metkit_marsrequest_merge(res.ctype(), other.ctype()) res.validate() return res def __iter__(self) -> Iterator[tuple[str, list[str]]]: for param in self.keys(): yield param, self[param] def __getitem__(self, param: str) -> str | list[str]: nvalues = self.num_values(param) values = [] for index in range(nvalues): cvalue = ffi.new("const char **") lib.metkit_marsrequest_value(self.__request, ffi_encode(param), index, cvalue) value = ffi_decode(cvalue[0]) if nvalues == 1: return value values.append(value) return values def __contains__(self, param: str) -> bool: has = ffi.new("bool *", False) lib.metkit_marsrequest_has_param(self.__request, ffi_encode(param), has) return has[0] def __setitem__(self, param: str, values: int | str | list[str]): if isinstance(values, (str, int)): values = [values] cvals = [] for value in values: if isinstance(value, int): value = str(value) cvals.append(ffi.new("const char[]", value.encode("ascii"))) lib.metkit_marsrequest_set( self.__request, ffi_encode(param), ffi.new("const char*[]", cvals), len(values), ) def __eq__(self, other: "MarsRequest") -> bool: if self.verb() != other.verb(): return False expanded = self.expand() other_expanded = other.expand() return dict(expanded) == dict(other_expanded) def parse_mars_request(file_or_str: IO | str, strict: bool = False) -> list[MarsRequest]: """ Function for parsing mars request from file object or string. Params ------ file_or_str: string or file-like object, containing mars request strict: bool, whether to raise error or warning when request is not compatible with MARS language definition. In the case of warning, when False, the incompatible parameters are unset from the request. Returns ------- list of Request """ crequest_iter = ffi.new("metkit_requestiterator_t **") if isinstance(file_or_str, str): lib.metkit_parse_marsrequests(ffi_encode(file_or_str), crequest_iter, strict) else: lib.metkit_parse_marsrequests( ffi_encode(file_or_str.read()), crequest_iter, strict ) request_iter = ffi.gc(crequest_iter[0], lib.metkit_requestiterator_delete) requests = [] while lib.metkit_requestiterator_next(request_iter) == lib.METKIT_ITERATOR_SUCCESS: new_request = MarsRequest() lib.metkit_requestiterator_current(request_iter, new_request.ctype()) requests.append(new_request) return requests class MetKitException(RuntimeError): """Raised when MetKit library throws exception""" pass class CFFIModuleLoadFailed(ImportError): """Raised when the shared library fails to load""" pass class PatchedLib: """ Patch a CFFI library with error handling Finds the header file associated with the MetKit C API and parses it, loads the shared library, and patches the accessors with automatic python-C error handling. """ def __init__(self): libName = findlibs.find("metkit") if libName is None: raise RuntimeError("MetKit library not found") ffi.cdef(self.__read_header()) self.__lib = ffi.dlopen(libName) # All of the executable members of the CFFI-loaded library are functions in the MetKit # C API. These should be wrapped with the correct error handling. Otherwise forward # these on directly. for f in dir(self.__lib): try: attr = getattr(self.__lib, f) setattr( self, f, self.__check_error(attr, f) if callable(attr) else attr ) except Exception as e: print(e) print("Error retrieving attribute", f, "from library") # Initialise the library, and set it up for python-appropriate behaviour self.metkit_initialise() # Check the library version versionstr = ffi.string(self.metkit_version()).decode("utf-8") if versionstr != __version__: warnings.warn(f"Metkit library version {versionstr} does not match python version {__version__}") def __read_header(self): with open(os.path.join(os.path.dirname(__file__), "metkit_c.h"), "r") as f: return f.read() def __check_error(self, fn, name: str): """ If calls into the MetKit library return errors, ensure that they get detected and reported by throwing an appropriate python exception. """ def wrapped_fn(*args, **kwargs): # debug retval = fn(*args, **kwargs) # Some functions dont return error codes. Ignore these. if name in ["metkit_version", "metkit_git_sha1"]: return retval # error codes: if retval not in ( self.__lib.METKIT_SUCCESS, self.__lib.METKIT_ITERATOR_SUCCESS, self.__lib.METKIT_ITERATOR_COMPLETE, ): err = ffi_decode(self.__lib.metkit_get_error_string(retval)) msg = "Error in function '{}': {}".format(name, err) raise MetKitException(msg) return retval return wrapped_fn try: lib = PatchedLib() except CFFIModuleLoadFailed as e: raise ImportError() from e metkit-1.16.0/python/pymetkit/tests/000077500000000000000000000000001513171467200174345ustar00rootroot00000000000000metkit-1.16.0/python/pymetkit/tests/test_marsrequest.py000066400000000000000000000111321513171467200234160ustar00rootroot00000000000000from datetime import datetime, timedelta from contextlib import nullcontext as does_not_raise import pytest from pymetkit import parse_mars_request, MarsRequest, MetKitException request = """ retrieve, class=od, domain=g, expver=0001, levtype=sfc, stream=enfo, date=-1, time=12, param=151.128, grid=O640, step=0/to/24/by/6, target=test.grib, type=em retrieve, class=od, domain=g, expver=0001, levtype=pl, stream=enfo, date=-1, time=12, param=129, levelist=500, grid=O640, step=0/to/24/by/6, target=test.grib, type=em """ yesterday = (datetime.today() - timedelta(days=1)).strftime("%Y%m%d") def test_parse_file(tmpdir): request_file = f"{tmpdir}/requests" with open(request_file, "w") as f: f.write(request) requests = parse_mars_request(open(request_file, "r")) assert len(requests) == 2 for req in requests: assert req.verb() == "retrieve" assert len(req["step"]) == 5 assert req["date"] == yesterday assert "class" in requests[0] assert requests[1]["levelist"] == "500" # @todo: [1] no longer raises an exception. Disable until METK-126 is resolved. @pytest.mark.parametrize( "req_str, length, steps, strict, expectation", [ [request, 2, 5, False, does_not_raise()], # [request, 2, 5, True, pytest.raises(MetKitException)], [ "retrieve,class=od,date=-1,time=12,param=129,step=12,target=test.grib", 1, 1, False, does_not_raise(), ], ], ) def test_parse_string(req_str, length, steps, strict, expectation): with expectation: requests = parse_mars_request(req_str, strict) assert len(requests) == length for req in requests: assert req.num_values("step") == steps def test_empty_request(tmpdir): request_file = f"{tmpdir}/requests" with open(request_file, "w") as f: f.write("") requests = parse_mars_request(open(request_file, "r")) assert len(requests) == 0 def test_new_request(): req = MarsRequest("retrieve") assert req.verb() == "retrieve" req = MarsRequest("request", class_="od", type="pf", date=["20200101", "20200102"]) assert req["class"] == "od" assert req["type"] == "pf" assert req["date"] == ["20200101", "20200102"] def test_request_from_expand(): req = MarsRequest( "retrieve", **{ "class": "od", "domain": "g", "date": "-1", "expver": "0001", "step": range(0, 13, 6), }, ) expanded = req.expand() assert expanded.verb() == req.verb() assert expanded["date"] == yesterday assert "param" in expanded expanded.validate() assert req == expanded # @todo: [0] and [1] no longer raise an exception. Disable until METK-126 is resolved. @pytest.mark.parametrize( "extra_kv", [ # {"levelist": [500]}, # {"type": "cf", "number": [1, 2]}, {"class": "invalid"} ], ) def test_request_validate(extra_kv): request = { "class": "od", "domain": "g", "date": "-1", "expver": "0001", "step": range(0, 13, 6), "levtype": "sfc", } request.update(extra_kv) req = MarsRequest("retrieve", **request) with pytest.raises(MetKitException): req.validate() @pytest.mark.parametrize( "extra_kv, expectation", [ [{"levtype": "pl", "date": "-1"}, pytest.raises(MetKitException)], [{"levtype": "sfc", "date": "-1", "type": "em"}, pytest.raises(ValueError)], [{"levtype": "sfc", "date": "20230101"}, does_not_raise()], ], ) def test_request_merge(extra_kv, expectation): request = { "class": "od", "domain": "g", "expver": "0001", "step": range(0, 13, 6), } req = MarsRequest("retrieve", **request, date="-1", levtype="sfc") other_req = MarsRequest("retrieve", **request, **extra_kv) with expectation: req.merge(other_req) @pytest.mark.parametrize( "verb, updates, expected", [["retrieve", {"date": 20230101, "param": 130}, True], ["compute", {}, False]], ) def test_request_equality(verb, updates, expected): init_request = { "class": "od", "domain": "g", "date": "20230101", "param": "130", "expver": "0001", "step": range(0, 13, 6), } req = MarsRequest( "retrieve", **init_request, ) second_request = {**init_request, **updates} req2 = MarsRequest(verb, **second_request) assert (req == req2) == expected metkit-1.16.0/share/000077500000000000000000000000001513171467200142055ustar00rootroot00000000000000metkit-1.16.0/share/CMakeLists.txt000066400000000000000000000000331513171467200167410ustar00rootroot00000000000000add_subdirectory( metkit ) metkit-1.16.0/share/metkit/000077500000000000000000000000001513171467200155025ustar00rootroot00000000000000metkit-1.16.0/share/metkit/.gitignore000066400000000000000000000000131513171467200174640ustar00rootroot00000000000000*.list tmp metkit-1.16.0/share/metkit/CMakeLists.txt000066400000000000000000000011071513171467200202410ustar00rootroot00000000000000list( APPEND files language.yaml modifiers.yaml reportype.yaml obstype.yaml paramids.yaml params.yaml params-static.yaml param-matching.yaml chemids.yaml bufr-subtypes.yaml axis.yaml shortname-context.yaml ) foreach( _file ${files} ) configure_file( ${_file} ${CMAKE_BINARY_DIR}/share/metkit/${_file} COPYONLY ) if( HAVE_METKIT_CONFIG ) install( FILES ${CMAKE_BINARY_DIR}/share/metkit/${_file} DESTINATION "share/metkit" PERMISSIONS OWNER_WRITE OWNER_READ GROUP_READ WORLD_READ ) endif() endforeach() add_subdirectory( odb ) metkit-1.16.0/share/metkit/axis.yaml000066400000000000000000000015351513171467200173360ustar00rootroot00000000000000--- axes: - class - country - type - stream - levtype - origin - product - section - method - system - date - refdate - hdate - offsetdate - time - offsettime - anoffset - reference - dataset - step - fcmonth - fcperiod - leadtime - opttime - expver - domain - diagnostic - iteration - quantile - number - levelist - latitude - longitude - range - param - chem - wavelength - timespan - stattype - ident - obstype - instrument - frequency - direction - channel - obsgroup - reportype - activity - experiment - generation - model - realization - resolution - year - month - bcmodel - icmodel - grib - georef - coeffindex metkit-1.16.0/share/metkit/bufr-subtypes.yaml000066400000000000000000000033671513171467200212110ustar00rootroot00000000000000--- subtypes: - [1, 1] - [2, 1] - [3, 1] - [4, 1] - [7, 1] - [9, 1] - [11, 1] - [12, 1] - [13, 1] - [14, 1] - [19, 1] - [21, 1] - [22, 1] - [23, 1] - [26, 1] - [28, 1] - [31, 8] - [32, 8] - [49, 2] - [51, 2] - [53, 2] - [54, 2] - [55, 2] - [56, 2] - [57, 2] - [59, 2] - [60, 2] - [61, 2] - [62, 2] - [63, 2] - [65, 2] - [71, 2] - [72, 2] - [73, 2] - [75, 2] - [82, 3] - [83, 3] - [84, 3] - [85, 3] - [86, 3] - [87, 3] - [88, 3] - [89, 3] - [91, 4] - [92, 4] - [95, 4] - [96, 4] - [97, 4] - [101, 5] - [102, 5] - [103, 5] - [104, 5] - [106, 5] - [109, 5] - [110, 1] - [111, 5] - [112, 5] - [113, 5] - [121, 12] - [122, 12] - [123, 12] - [124, 12] - [125, 6] - [126, 12] - [127, 12] - [129, 2] - [130, 2] - [131, 6] - [132, 6] - [133, 6] - [136, 12] - [137, 12] - [138, 12] - [139, 12] - [140, 1] - [142, 7] - [143, 7] - [144, 7] - [145, 7] - [146, 7] - [147, 1] - [148, 7] - [149, 7] - [150, 7] - [151, 7] - [153, 12] - [154, 2] - [155, 2] - [156, 2] - [159, 9] - [161, 2] - [162, 9] - [164, 10] - [165, 1] - [170, 1] - [172, 1] - [176, 1] - [178, 1] - [180, 1] - [181, 1] - [182, 1] - [184, 1] - [189, 3] - [190, 3] - [201, 12] - [202, 12] - [203, 30] - [204, 30] - [206, 2] - [207, 2] - [208, 2] - [209, 2] - [210, 12] - [211, 2] - [212, 3] - [213, 12] - [214, 12] - [216, 2] - [217, 12] - [218, 12] - [220, 12] - [224, 12] - [226, 2] - [227, 2] - [228, 3] - [230, 5] - [231, 5] - [233, 12] - [235, 12] - [237, 1] - [240, 2] - [244, 30] - [245, 12] - [246, 12] - [250, 2] - [251, 2] - [252, 21] - [255, 2] metkit-1.16.0/share/metkit/check-params-yaml.py000077500000000000000000000010671513171467200213610ustar00rootroot00000000000000#!/usr/bin/env python import MySQLdb import yaml import re import os db = MySQLdb.connect( "grib-param-db-prod.ecmwf.int", os.environ['PARAM_DB_USER'], os.environ['PARAM_DB_PASSWORD'], "param") cursor = db.cursor() with open("params.yaml") as f: PARAMS = yaml.load(f.read()) for entry in PARAMS: when, parms = entry for p in parms: cursor.execute("select count(*) from param where id=%s" % p) for data in cursor.fetchall(): if data[0] == 0: print("%s: %s is not in param DB" % (when, p)) metkit-1.16.0/share/metkit/chemids.yaml000066400000000000000000000162001513171467200200010ustar00rootroot00000000000000--- # File automatically generated by make-yaml.py --chem # Do not edit - [2, CO, Carbon monoxide] - [3, H2O2, Hydrogen peroxide] - [4, CH4_c, Methane (chemistry)] - [5, HCHO, Formaldehyde] - [6, HNO3, Nitric acid] - [7, CH3OOH, Methyl peroxide] - [8, SO2_v, Volcanic sulphur dioxide] - [9, par, Paraffins] - [10, C2H4, Ethene] - [11, Rn, Radon] - [12, ALD2, Aldehydes] - [13, PAN, Peroxyacetyl nitrate] - [14, ROOH, Peroxides] - [15, NO3_org, Organic nitrates] - [16, C5H8, Isoprene] - [17, NO2, Nitrogen dioxide] - [18, DMS, Dimethyl sulfide] - [19, NH3, Ammonia] - [20, SO4, Sulfate] - [21, NH4, Ammonium] - [22, MSA, Methane sulfonic acid] - [23, CH3COCHO, Methyl glyoxal] - [24, O3S, Stratospheric ozone] - [25, CO2, Carbon dioxide] - [26, Pb, Lead] - [27, 'NO', Nitrogen monoxide] - [28, HO2_r, Hydroperoxy radical] - [29, CH3O2_r, Methylperoxy radical] - [30, OH_r, Hydroxyl radical] - [31, N2O, Nitrous oxide] - [32, NO3, Nitrate radical] - [33, N2O5, Dinitrogen pentoxide] - [34, HO2NO2, Pernitric acid] - [35, C2O3_r, Peroxy acetyl radical] - [36, ROR, Organic ethers] - [37, rxpar, PAR budget corrector] - [38, xo2, NO to NO2 operator] - [39, xo2n, NO to alkyl nitrate operator] - [40, NH2, Amine] - [41, psc, Polar stratospheric cloud] - [42, CH3OH, Methanol] - [43, HCOOH, Formic acid] - [44, MCOOH, Methacrylic acid] - [45, C2H6, Ethane] - [46, C2H5OH, Ethanol] - [47, C3H8, Propane] - [48, C3H6, Propene] - [49, C10H16, Terpenes] - [50, ISPD, Methacrolein MVK] - [52, CH3COCH3, Acetone] - [53, aco2, Acetone product] - [55, hypropo2] - [56, noxa, Nitrogen oxides Transp] - [57, CO2_c, Carbon dioxide (chemistry)] - [58, N2O_c, Nitrous oxide (chemistry)] - [59, H2O_c, Water vapour (chemistry)] - [60, O2, Dioxygen] - [61, O2_1s, Singlet sigma dioxygen] - [62, O2_1d, Singlet Delta dioxygen] - [63, OClO, Chlorine dioxide] - [64, ClONO2, Chlorine nitrate] - [65, HOCl, Hypochlorous acid] - [66, Cl2, Chlorine] - [67, ClNO2, Nitryl chloride] - [68, HBr, Hydrogen bromide] - [69, Cl2O2, Dichlorine dioxide] - [70, HOBr, Hypobromous acid] - [71, CFC11, Trichlorofluoromethane] - [72, CFC12, Dichlorodifluoromethane] - [73, CFC113, Trichlorotrifluoroethane] - [74, CFC114, Dichlorotetrafluoroethane] - [75, CFC115, Chloropentafluoroethane] - [76, ccl4, Tetrachloromethane] - [77, ch3ccl3, Methyl chloroform] - [78, CH3Cl, Methyl chloride] - [79, hcfc22, Chlorodifluoromethane] - [80, CH3Br, Methyl bromide] - [82, ha1211, Bromochlorodifluoromethane] - [83, ha1301, Trifluorobromomethane] - [85, H2SO4, Sulfuric acid] - [86, HONO, Nitrous acid] - [93, DIEN, Butadiene] - [94, C2H5OOH, Ethyl hydroperoxide] - [96, CH3COOH, Acetic acid] - [98, CH3CHO, Acetaldehyde] - [99, tol, Toluene and less reactive aromatics] - [100, xyl, Xylene and more reactive aromatics] - [101, GLYALD, Glycolaldehyde] - [102, CRESOL] - [104, CH3COOOH, Peracetic acid] - [105, KET, Ketones] - [106, EO2, Hoch2ch2o2] - [107, GLYOXAL] - [108, EO, Hoch2ch2o] - [109, DCB, Unsaturated dicarbonyls] - [110, MACR, Methacrolein] - [111, UDD, Unsaturated hydroxy dicarbonyl] - [112, C3H7O2, Isopropyldioxidanyl] - [113, HKET, Hydroxy ketone] - [114, C3H7OOH, Isopropyl hydroperoxide] - [115, PO2, C3h6oho2] - [116, POOH, C3h6ohooh] - [118, HYAC, Hydroxyacetone] - [119, PAA, Peroxyacetic acid] - [124, BIGENE, Lumped alkenes] - [126, BIGALK, Lumped alkanes] - [129, NOx, Nitrogen oxides] - [138, MVK, Methylvinylketone] - [139, PhO, Phenoxy radical] - [155, Ox, Oxides] - [161, ISOPOOH, Hoch2c(ooh)(ch3)ch=ch2] - [163, DMSO, Dimethyl sulfoxyde] - [166, H2S, Hydrogensulfide] - [168, NOy, All nitrogen oxides] - [169, cly, Chlorine family] - [171, bry, Bromine family] - [173, N, Nitrogen atom] - [174, ClO, Chlorine monoxide] - [175, Cl, Chlorine atom] - [176, BrO, Bromine monoxide] - [177, h_c, Hydrogen atom] - [178, ch3, Methyl group] - [186, sog1, Condensable gas type 1] - [187, sog2a, Condensable gas type 2a] - [188, sog2b, Condensable gas type 2b] - [189, SO3, Sulfur trioxide] - [190, OCS_c, Carbonyl sulfide] - [191, Br, Bromine atom] - [192, Br2, Bromine] - [193, BrCl, Bromine monochloride] - [194, BrONO2, Bromine nitrate] - [195, CH2Br2, Dibromomethane] - [196, CH3O, Methoxy radical] - [197, CHBr3, Tribromomethane] - [198, cloo, Asymmetric chlorine dioxide radical] - [199, H2, Dihydrogen] - [200, HCl, Hydrogen chloride] - [201, HCO, Formyl radical] - [202, HF, Hydrogen fluoride] - [203, O, Oxygen atom] - [204, O_1d, Excited oxygen atom] - [205, O_3p, Ground state oxygen atom] - [222, AROO2, Aromatic peroxide radical] - [224, CH3CN, Acetonitrile] - [225, CH3O2NO2, Methyl peroxy nitrate] - [226, HCN, Hydrogen cyanide] - [227, HPALD1, Hydroperoxy aldehydes type 1] - [228, HPALD2, Hydroperoxy aldehydes type 2] - [229, ISOPBO2, Isoprene peroxy type B] - [230, ISOPDO2, Isoprene peroxy type D] - [231, gO3, GEMS ozone] - [232, SF6, Sulphur hexafluoride] - [233, SO2, Sulphur dioxide] - [236, O3, Ozone] - [311, ole, Olefins] - [331, aVOC, Anthropogenic volatile organic compounds] - [332, bbVOC, Biomass burning volatile organic compounds] - [359, H2O, Water vapour] - [404, CH4, Methane] - [431, C7H8, Toluene] - [432, C6H6, Benzene] - [433, C8H10, Xylene] - [438, C4H10, Butene] - [900, aer_NO3, Nitrate] - [901, aer_seasalt_003_05, Sea salt aerosol (0.03 - 0.5 um)] - [902, aer_seasalt_05_5, Sea salt aerosol (0.5 - 5 um)] - [903, aer_seasalt_5_20, Sea salt aerosol (5 - 20 um)] - [904, aer_dust_003_055, Dust aerosol (0.03 - 0.55 um)] - [905, aer_dust_055_09, Dust aerosol (0.55 - 0.9 um)] - [906, aer_dust_09_20, Dust aerosol (0.9 - 20 um)] - [907, aer_hicorgmat, Hydrophilic organic matter aerosol] - [908, aer_hocorgmat, Hydrophobic organic matter aerosol] - [909, aer_hicblackcarb, Hydrophilic black carbon aerosol] - [910, aer_hocblackcarb, Hydrophobic black carbon aerosol] - [911, aer_sulph, Sulphate aerosol] - [912, aer_nitrfine, Nitrate fine mode aerosol (<= 2.5 um)] - [913, aer_nitrcoars, Nitrate coarse mode aerosol (>2.5 um)] - [914, aer_nh4, Ammonium aerosol] - [915, aer_biosecorg, Biogenic secondary organic aerosol] - [916, aer_antsecorg, Anthropogenic secondary organic aerosol] - [917, strataer, Stratospheric aerosol] - [918, SOA, Secondary particulate organic matter dry] - [919, aer_biosecorg_pre, Biogenic secondary organic aerosol precursor] - [920, aer_antsecorg_pre, Anthropogenic secondary organic aerosol precursor] - [921, aer_so2_pre, SO2 precursor] - [922, aer_total, Total aerosol] - [923, aer_sm, Aerosol small mode] - [924, aer_lm, Aerosol large mode] - [925, aer_dust_09_2p5, Dust aerosol (0.9 - 2.5 um)] - [926, aer_dust_2p5_5, Dust aerosol (2.5 - 5.0 um)] - [927, aer_dust_5_10, Dust aerosol (5.0 - 10.0 um)] - [928, aer_dust_10_20, Dust aerosol (10.0 - 20.0 um)] - [929, aer_pm_1, Particulate matter <= 1 um] - [930, aer_pm_2p5, Particulate matter <= 2.5 um] - [931, aer_pm_10, Particulate matter <= 10 um] - [932, volash, Volcanic Ash] - [933, aer_blackcarb, Black carbon organic aerosol] - [934, aer_orgmat, Organic matter aerosol] - [935, aer_dust, Dust aerosol] - [936, aer_seasalt, Sea salt aerosol] - [937, aer_dust_1, Dust aerosol smaller than 1 um] - [938, aer_dust_2p5, Dust aerosol smaller than 2.5 um] - [939, aer_dust_10, Dust aerosol smaller than 10 um] - [940, aer_dust_20, Dust aerosol smaller than 20 um] - [941, SO4_v, Volcanic Sulphate] metkit-1.16.0/share/metkit/language.yaml000066400000000000000000001145711513171467200201620ustar00rootroot00000000000000--- _field: &_field style: type: enum values: - [dissemination] class: category: data defaults: - vals: [od] flatten: false type: enum values: - [a5, ECMWF Atmospheric Composition reanalysis version 5] - [ai, operational aifs] - [at, austria] - [be, belgium] - [c3, c3s] - [ce, cems] - [ch, switzerland] - [ci, cerise] - [co, cosmo] - [cr, cams research] - [cs, ecsn] - [d1, destine] - [de, germany] - [dk, denmark] - [dm, demeter] - [dt, dts] - [e2, e20c] - [e4, reanalyse40] - [e6, era6] - [ea, era5, esat] - [ed, eerie] - [ef, efas] - [ei, era interim] - [el, eldas] - [em, e20cm] - [en, ensembles] - [ep, cera-20c, cera20c] - [er, reanalyse] - [es, spain] - [et, cera-sat, cerasat] - [fi, finland] - [fr, france] - [gf, glofas] - [gg, greenhouse gases] - [gr, greece] - [gw, global wildfire information system] - [hr, croatia] - [hu, hungary] - [ie, ireland] - [is, iceland] - [it, italy] - [j5, jra55] - [l5, era5l] - [l6, era6l] - [la, aladin-laef, laef, lace] - [lw, WMO lead centre wave forecast verification] - [ma, metaps] - [mc, macc] - [me, mersea] - [ml, machine learning] - [ms, member states] - [ng, nextgems] - [nl, netherlands] - ['no', norway] - [nr, ncep 20cr, 20cr] - [o6, 'ocean 6 reanalysis'] - [od, operations] - [pe, permanent experiment] - [pt, portugal] - [pv, provost] - [rd, research] - [rm, euro4m] - [rr, regional reanalysis] - [s2, s2s] - [se, sweden] - [si, slovenia] - [sr, sreps] - [te, test] - [ti, tigge] - [to, tost] - [tr, turkey] - [uk, united kingdom] - [ul, ulysses] - [ur, uerra] - [yp, yopp] - [yt, yotc] type: category: data defaults: - vals: [an] flatten: false type: enum values: - [3g, 3d variational gradients] - [3v, 3d variational analysis] - [4g, 4d variational gradients] - [4i, 4d variational increments] - [4v, 4d variational analysis] - [ab, analysis bias] - [af, analysis feedback] - [ai, analysis input] - [an, analysis] - [as, adjoint singular vector] - [bf, bias-corrected forecast] - [cd, climate distribution] - [cf, control forecast] - [ci, clustering information] - [cl, climatology] - [cm, cluster means] - [cr, cluster representative] - [cs, cluster std deviations] - [cv, calibration validation forecast] - [ea, errors in analysis] - [ed, empirical distribution] - [ef, errors in first guess] - [efi, extreme forecast index] - [efic, extreme forecast index control] - [em, ensemble mean] - [eme, ensemble data assimilation model errors] - [emtm, ensemble mean of temporal mean] - [ep, event probability] - [es, ensemble standard deviation] - [est, ensemble statistics] - [estdtm, ensemble standard deviation of temporal mean] - [fa, forecast accumulation] - [fb, feedback] - [fc, forecast] - [fcdfb, forecast departures feedback] - [fcmax, forecast maximum] - [fcmean, forecast mean] - [fcmin, forecast minimum] - [fcstdev, forecast standard deviation] - [ff, flux forcing realtime] - [fg, first guess] - [fp, forecast probability] - [fsoifb, forecast sensitivity to observations impact feedback] - [fu, fill-up] - [fx, flux forcing] - [ga, gfas analysis] - [gbf, bias-corrected gridbox] - [gai, gridded analysis input] - [go, gridded observations] - [gsd, gridded satellite data] - [gwt, weather type gridbox] - [hcmean, hindcast mean] - [ia, init. analysis] - [icp, initial condition perturbation] - [mpp, model physics perturbation] - [if, interim forecast] - [im, images] - [me, model errors] - [mfb, mondb feedback] - [oai, odb analysis input] - [ob, observations] - [of, ocean forward] - [ofa, odb feedback from analysis] - [ofb, odb feedback] - [oi, oi analysis] - [oldim, old format images] - [or, ocean reanalysis] - [pa, perturbed analysis] - [pb, probability boundary] - [pd, probability distribution] - [pf, perturbed forecast] - [pfc, point values] - [ppm, point value metrics] - [s3, climate 30 days simulation] - [ses, scaled ensemble standard deviation] - [sf, sensitivity forecast] - [sfb, summary feedback] - [sfo, simulations with forcing] - [sg, sensitivity gradient] - [si, climate simulation] - [sim, simulated images] - [sot, shift of tails] - [ssd, simulated satellite data] - [sv, singular vector] - [svar, signal variance] - [taem, time average ensemble mean] - [taes, time average ensemble standard deviation] - [tpa, time processed analysis] - [tf, trajectory forecast] - [tu, tube] - [wem, weighted ensemble mean] - [wes, weighted ensemble standard deviation] - [wp, weather parameters] stream: category: data flatten: false type: enum values: - [amap, analysis for multianalysis project] - [ammc, melbourne] - [cher, ch, chernobyl] - [clte, climate, Climate run output] - [clmn, climate-monthly, Climate run monthly means output] - [cnrm, meteo france climate centre] - [cwao, montreal] - [dacl, daily climatology] - [dacw, daily climatology wave] - [dahc, daily archive hindcast] - [dame] - [dcda, atmospheric model (delayed cutoff)] - [dcwv, wave model (delayed cutoff)] - [edmm, ensemble data assimilation monthly means] - [edmo, ensemble data assimilation monthly means of daily means] - [edzw, offenbach] - [eefh, extended ensemble forecast hindcast] - [eefo, extended ensemble prediction system] - [eehs, extended ensemble forecast hindcast statistics] - [efas, european flood awareness system (efas)] - [efcl, european flood awareness system (efas) climatology] - [efhc, ensemble forecast hindcasts (obsolete)] - [efho, ensemble forecast hindcast overlap] - [efhs, ensemble forecast hindcast statistics] - [efov, ensemble forecast overlap] - [efrf, european flood awareness system (efas) reforecasts] - [efse, european flood awareness system (efas) seasonal forecasts] - [efsr, european flood awareness system (efas) seasonal reforecasts] - [egrr, exeter, bracknell] - [ehmm, combined multi-model hindcast monthly means] - [elda, ensemble long window data assimilation] - [enda, ensemble data assimilation] - [enfh, ensemble forecast hindcasts] - [enfo, ef, ensemble prediction system] - [enwh, ensemble forecast wave hindcasts] - [esmm, combined multi-model monthly means] - [espd, ensemble supplementary data] - [ewda, ensemble wave data assimilation] - [ewhc, wave ensemble forecast hindcast (obsolete)] - [ewho, ensemble forecast wave hindcast overlap] - [ewla, ensemble wave long window data assimilation] - [ewmm, ensemble wave data assimilation monthly means] - [ewmo, ensemble wave data assimilation monthly means of daily means] - [fgge, fg] - [fsob, forecast sensitivity to observations] - [fsow, forecast sensitivity to observations wave] - [gfas, global fire assimilation system] - [gfra, global fire assimilation system reanalysis] - [kwbc, washington] - [lfpw, paris, toulouse] - [lwda, long window daily archive] - [lwwv, long window wave] - [ma, means archive] - [maed, multianalysis ensemble data] - [mawm, wave anomaly means] - [mawv, multianalysis wave data] - [mdfa, monthly means of daily forecast accumulations] - [mfam, anomaly means] - [mfaw, wave anomalies] - [mfhm, hindcast means] - [mfhw, monthly forecast hindcasts wave] - [mfwm, wave real-time means] - [mhwm, wave hindcast means] - [mmaf, multi-model multi-annual forecast] - [mmam, multi-model multi-annual forecast means] - [mmaw, multi-model multi-annual forecast wave] - [mmsa, multi-model seasonal forecast monthly anomalies] - [mmsf, multi-model seasonal forecast] - [mmwm, multi-model multi-annual forecast wave means] - [mnfa, anomalies] - [mnfc, real-time] - [mnfh, hindcasts] - [mnfm, real-time means] - [mnfw, wave real-time] - [mnth, mo, monthly, monthly means] - [mnvr, monthly variance and covariance data using g. boer's step function] - [moda, monthly means of daily means] - [mofc, monthly forecast] - [mofm, monthly forecast means] - [monr, monthly means using g. boer's step function] - [mpic, max plank institute] - [msda, monthly standard deviation and covariance of daily means] - [msdc, mv, monthly standard deviation and covariance] - [msmm, multi-model seasonal forecast atmospheric monthly means] - [mswm, multi-model seasonal forecast wave monthly means] - [ocda, ocean data assimilation] - [ocea, ocean] - [olda, ocean Long window data assimilation] - [oper, da, daily archive, atmospheric model] - [rjtd, tokyo] - [scda, atmospheric model (short cutoff)] - [scwv, wave model (short cutoff)] - [seap, sensitive area prediction] - [seas, seasonal forecast] - [sens, sf, sensitivity forecast] - [sfmm, seasonal forecast atmospheric monthly means] - [smma, seasonal monthly means anomalies] - [sttd, Statistics of deterministic data] - [stte, Statistics of ensemble data] - [supd, sd, deterministic supplementary data] - [swmm, seasonal forecast wave monthly means] - [toga, tg] - [ukmo, ukmo climate centre] - [waef, we, wave ensemble forecast] - [wamd, wave monthly means of daily means] - [wamf, wave monthly forecast] - [wamo, wave monthly means] - [wams, multi-model seasonal forecast wave] - [wasf, wave seasonal forecast] - [wave, wv, wave model] - [wavm, wave model (standalone)] - [weef, wave extended ensemble forecast] - [weeh, wave extended ensemble forecast hindcast] - [wees, wave extended ensemble forecast hindcast statistics] - [wehs, wave ensemble forecast hindcast statistics] - [weov, wave ensemble forecast overlap] - [wfas, global flood awareness system (glofas)] - [wfcl, global flood awareness system (glofas) climatology] - [wfrf, global flood awareness system (glofas) reforecasts] - [wfse, global flood awareness system (glofas) seasonal forecasts] - [wfsr, global flood awareness system (glofas) seasonal reforecasts] - [wmfm, wave monthly forecast means] - [wvhc, wave hindcast] product: category: data type: enum values: - [inst, instantaneous] - [tims, time-series] - [tavg, time-average] - [tacc, time-accumulation] section: category: data type: enum values: - [h, horizontal] - [v, vertical] - [z, zonal] - [m, meridional] range: category: data type: any use: flatten: false multiple: true type: enum values: - [frequent, f] - [infrequent, i] - [normal, n] - compare - [monthly run] - intent - disk # - [bc, boundary conditions] # - [monday, mon] # - [tuesday, tue] # - [wednesday, wed] # - [thursday, thu] # - [friday, fri] # - [saturday, sat] # - [sunday, sun] # product: # %if LEVTYPE = DP # %and TYPE = OR # %and (%not PRODUCT) # %then # %warning "Default PRODUCT for Ocean ReAnalysis set to Instantaneous" # %set PRODUCT = INST expver: category: data flatten: false type: expver defaults: - vals: ['0001'] dataset: category: data multiple: false type: - context: class: [d1] type: enum values: - [climate-dt, Climate change adaptation digital twin] - [extremes-dt, Weather and geophysical extremes digital twin] - [on-demand-climate-dt, On-demand climate change adaptation digital twin] - [on-demand-extremes-dt, On-demand weather and geophysical extremes digital twin] - type: lowercase model: category: data type: - context: class: [ms] country: [it] type: enum values: - [lm] - [hrm] - [wam] - type: enum values: - [ecmf] - [edzw] - [egrr] - [lfpw] - [kwbc] - [none] - [hrm] - [ifs, IFS with no ocean model] - [ifs-nemo, IFS with NEMO ocean model] - [ifs-fesom, IFS with FESOM ocean model] - [icon, ICON-A with ICON-O ocean model] - [lisflood] - [lm] - [lam] - [aifs] - [aifs-single] - [aifs-single-mse] - [aifs-ens] - [aifs-ens-crps] - [aifs-ens-diff] - [aifs-compo-single] - [aifs-compo-ens] - [aifs-compo-single-mse] - [aifs-compo-ens-crps] - [alaro] - [arome] - [harmonie-arome] - [glob, global] - [ecpoint] georef: category: data type: lowercase repres: flatten: false multiple: false type: enum values: - [bu, 'bufr'] - [sh, 'spherical harmonics'] - [ll, 'lat long grid'] - [gg, 'gaussian grid'] - [sv, 'space view'] - [og, 'ocean grid'] - [np] - [rl] coeffindex: category: data multiple: true type: to-by-list by: 1 unset: - context: type: op: '!' vals: [me, eme] obsgroup: category: data multiple: true type: enum values: # - [conventional] - [sat, satellite] - [ers1] - [trmm] - [qscat] - [reo3] # reo3 needs to stay for compatibility # previously in "obsgroups.def" - [hirs, 1] - [amsua, 2] - [amsub, 3] - [mhs, 4] - [geos, 5] - [resat, 6] - [meris, 7] - [gpsro, 8] - [satob, 9] - [scatt, 10] - [ssmi_as, 11, SSMI ALL-SKY] - [iasi, 12] - [airs, 13] - [ssmis_as, 14, SSMIS ALL-SKY] - [tmi_as, 15, TMI ALL-SKY] - [amsre_as, 16, AMSRE ALL-SKY] - [conv, 17] - [smos, 19] - [windsat_as, 20, WINDSAT ALL-SKY] - [ssmi, 21] - [amsua_as, 22, AMSUA ALL-SKY] - [amsre, 23] - [tmi, 24] - [ssmis, 25] - [gbrad, 26] - [mwhs, 27] - [mwts, 28] - [mwri_as, 29, MWRI ALL-SKY] - [iras, 30] - [msu, 31] - [ssu, 32] - [vtpr1, 33] - [vtpr2, 34] - [atms, 35] - [resat_ak, 36, RESAT AVERAGING KERNELS] - [cris, 37] - [wave_ip, 38, WAVE INTEGRATED PARAMETERS] - [wave_sp, 39, WAVE SPECTRA] - [raingg, 40] - [sfc_ms, 41, SURFACE MULTISENSOR] - [amsr2_as, 42, AMSR-2 ALL-SKY] - [saphir_as, 43, SAPHIR ALL-SKY] - [amsub_as, 44, AMSUB ALL-SKY] - [mhs_as, 45, MHS ALL-SKY] - [dwl, 46, DOPPLER WIND LIDAR] - [iris, 47] - [alt, 48, Altimeter] - [aatsr, 49] - [atms_as, 50, ATMS ALL-SKY] - [gmi_as, 51, GMI ALL-SKY] - [godae_sst, 52, GODAE SEA SURFACE TEMPERATURES] - [atovs_ms, 53, ATOVS MULTISENSOR] - [atmospheric_composition, 54, ATMOSPHERIC COMPOSITION] - [non_sfc_ms, 55, NON-SURFACE MULTISENSOR] - [mwts2, 56] - [ssmi_1d, 57, SSMI 1DVAR TCWV CLOUDY-SKY] - [mwhs2_as, 58, MWHS2 ALL-SKY] - [ssmt2, 59] - [smap, 60] - [tovs_ms, 61, TOVS MULTISENSOR] - [cloud_r, 62, CLOUD REFLECTIVITY] - [cloud_l, 63, CLOUD LIDAR] - [satellite_lightning, 64, SATELLITE LIGHTNING] - [geos_vis, 65, GEOS VIS] - [oconv, 66] - [mwts3_as, 67, MWTS3 All-sky] - [giirs, 68] - [hiras, 69] - [tropics_as, 70, TROPICS All-sky] - [ssmt1, 71] - [ssmt1_as, 72, SSMT1 All-sky] - [mws_as, 73, MWS All-sky] - [mwiici_as, 74, MWIICI All-sky] - [aws_as, 75, AWS All-sky] - [leos_vis, 76, LEOS VIS] - [ssh, 77] - [sirs, 78] - [scr, 79] - [scams_as, 80, SCAMS All-sky] - [nems_as, 81, NEMS All-sky] - [amsr3_as, 82, AMSR-3 All-sky] - [irs, 83] - [iasi_ng, 84, IASI-NG] - [smap_as, 85, SMAP All-sky] - [ssmt2_as, 86, SSMT2 All-sky] - [test, 99] reportype: category: data type: any multiple: true # rdbprefix levtype: category: data aliases: [levtyp] defaults: - vals: [pl] flatten: false type: [enum, integer] values: - [cat, category] - [dp, depth] - [layer] - [al, abstract levels] - [ml, model levels] - [pl, pressure levels] - [hl, height levels] - [pt, potential temperature] - [pv, potential vorticity] - [sfc, surf, surface] # sl ?? - [sol, surface other (multi)levels] - [wv, ocean wave] - [o2d, ocean surface] - [o3d, ocean model levels] levelist: category: data aliases: [leve,level,levellist] multiple: true type: to-by-list-float by: 1 param: category: data aliases: [parameter,parameters] multiple: true type: param defaults: - vals: [129] chem: category: data multiple: true type: enum values: "chemids.yaml" wavelength: category: data multiple: true type: range default: none timespan: category: data type: enum values: - [fs, from-start, fromstart] - [30m] - [1h] - [3h] - [6h] - [12h] - [18h] - [24h] - [48h] - [72h] - [120h] - [168h] - [240h] - [360h] - [none, inst, instantaneous] default: none multiple: false stattype: category: data type: enum values: - [moav, monthly average] - [momn, monthly minimum] - [momx, monthly maximum] - [mosd, monthly standard-deviation] - [daac, daily accumulation] - [daav, daily average] - [damn, daily minimum] - [damx, daily maximum] - [dasd, daily standard-deviation] - [moav_daav, monthly average of daily average] - [moav_damn, monthly average of daily minimum] - [moav_damx, monthly average of daily maximum] - [moav_dasd, monthly average of daily standard-deviation] - [momn_daav, monthly minimum of daily average] - [momn_damn, monthly minimum of daily minimum] - [momn_damx, monthly minimum of daily maximum] - [momn_dasd, monthly minimum of daily standard-deviation] - [momx_daav, monthly maximum of daily average] - [momx_damn, monthly maximum of daily minimum] - [momx_damx, monthly maximum of daily maximum] - [momx_dasd, monthly maximum of daily standard-deviation] - [mosd_daav, monthly standard-deviation of daily average] - [mosd_damn, monthly standard-deviation of daily minimum] - [mosd_damx, monthly standard-deviation of daily maximum] - [mosd_dasd, monthly standard-deviation of daily standard-deviation] multiple: false ################################################################# # year # decade # month date: category: data multiple: true type: date by: 1 defaults: - vals: [-1] year: category: data type: to-by-list multiple: true by: 1 month: category: data flatten: true type: enum multiple: true values: - [1, jan, january] - [2, feb, february] - [3, mar, march] - [4, apr, april] - [5, may] - [6, jun, june] - [7, jul, july] - [8, aug, august] - [9, sep, september] - [10, oct, october] - [11, nov, november] - [12, dec, december] hdate: category: data multiple: true type: date offsetdate: category: data multiple: true type: date fcmonth: category: data multiple: true by: 1 type: to-by-list fcperiod: category: data multiple: true type: any time: category: data multiple: true type: time by: 6h defaults: - vals: ['1200'] offsettime: category: data multiple: true type: time leadtime: category: data multiple: true type: any opttime: category: data multiple: true type: any step: category: data multiple: true by: 12 type: range defaults: - vals: [0] anoffset: category: data multiple: true type: integer reference: category: data multiple: true type: integer ################################################################# # cluster # probability number: category: data multiple: true type: to-by-list by: 1 quantile: category: data multiple: true type: to-by-list-quantile denominators: [2,3,4,5,10,100,1000] by: 1 domain: category: data type: - context: class: [ms] country: [it] type: enum values: - [italy] - [euroatl] - [europe] - [mediterranean] - type: enum flatten: false type: enum values: - [a, north west europe] - [b, north east europe, baltic and black sea] - [c, south west europe] - [d, south east europe] - [e, europe] - [f, fastex] - [g, globe, general european area] - [h] - [i] - [j] - [k] - [l] - [m, mediterranean] - ['n', northern hemisphere] - [o] - [p] - [q] - [r] - [s, southern hemisphere] - [t, tropics] - [u, tropics 2] - [v] - [w, western atlantic] - [x] - ['y'] - [z] bcmodel: category: data type: - context: class: [ms] country: [it] type: enum values: - [gme] - [ifs] icmodel: category: data type: - context: class: [ms] country: [it] type: enum values: - [gme] - [ifs] - [mvoi] - [nudging] - [3dvar] country: category: data multiple: false type: - context: class: [ms] type: enum values: - [it] - [de] grib: category: data multiple: false type: - context: class: [ms] country: [it] type: enum values: - [original] - [ecmwf] frequency: category: data multiple: true by: 1 type: to-by-list direction: category: data multiple: true by: 1 type: to-by-list diagnostic: category: data type: integer multiple: true iteration: category: data type: integer multiple: true channel: category: data type: integer multiple: true # TODO : Migration from old images to new images ident: category: data type: integer multiple: true instrument: category: data type: integer multiple: true # TODO : Migration from old images to new images method: category: data type: integer origin: category: data multiple: true type: enum values: - [aladinhuneps-omsz-eu] - [aladinlaef-zamg-eu] - [ammc, 1, melbourne] - [anso] - [aromeeps-mf-eu] - [babj, 38, beijing] - [cmcc] - [cnmc, 80] - [consensus, 255] - [cosmo] - [cosmodeeps-dwd-eu] - [cosmoleps-arpasimc-eu] - [crfc, 239, cerfacs] - [cwao, 54, montreal] - [dems] - [ecmf, 98, ecmwf] - [ecmf_ea, ecmwf_ea] - [ecmf_od, ecmwf_od] - [edzw, dwd, 78, offenbach] - [egrr, 74, exeter, bracknell] - [ekmi] - [enmi, 88, oslo] - [eswi] - [fapr] - [fnmo, fnmoc, 58, fleet numerical] - [fr-ms-ec] - [glameps-hirlamcons-eu] - [hadc, 247, hadley centre] - [hirlam-dmi-eu] - [ifmk, 246] - [ingv, 235] - [isac] - [knmi, 245] - [kwbc, 7, washington] - [lemm, 214, madrid] - [lfpw, 84, 85, paris, toulouse] - [lops] - [mogreps-mo-eua] - [nasa] - [niwa] - [no-ar-ce] - [no-ar-cw] - [no-ar-pa] - [nzkl] - [pearp-mf-eu] - [rjtd, 34, tokyo] - [rksl, 40, seoul] - [rums] - [sabm] - [sbsj, 46, cptec] - [se-al-ec] - [sreps-aemet-eua] - [srnwppeps-dwd-eua] - [vabb] - [vuwien, 244, university of vienna] system: category: data type: integer ####################################################################### # DestinE ClimateDT related keywords activity: category: data type: enum values: - [cmip6, Coupled Model Intercomparison Project Phase 6] - [scenariomip, Scenario Model Intercomparison Project] - [highresmip, High Resolution Model Intercomparison Project] - [story-nudging, Climate storylines by nudging to reanalysis] - [baseline, Baseline simulations for climate model evaluation] - [projections, Future climate projections] experiment: category: data type: enum values: - [hist, Historical] - [cont, Control] - [amip, Atmospheric Model Intercomparison Project] - [ssp1-1.9, Shared Socio-economic Pathways 1-1.9] - [ssp1-2.6, Shared Socio-economic Pathways 1-2.6] - [ssp2-4.5, Shared Socio-economic Pathways 2-4.5] - [ssp3-7.0, Shared Socio-economic Pathways 3-7.0] - [ssp5-8.5, Shared Socio-economic Pathways 5-8.5] - [tplus1.5k, Warmer world at 1.5 degrees K above pre-industrial temperatures] - [tplus2.0k, Warmer world at 2.0 degrees K above pre-industrial temperatures] - [tplus3.0k, Warmer world at 3.0 degrees K above pre-industrial temperatures] - [tplus4.0k, Warmer world at 4.0 degrees K above pre-industrial temperatures] - [abrupt4xco2, CO2 abruptly quadrupled and then held constant] generation: category: data type: integer realization: category: data type: integer resolution: category: data type: enum values: - [standard, Standard resolution model output with longer availability] - [high, High resolution model output with limited availability] # - product # - section # - refdate # - latitude # - longitude # - range ####################################################################### _observation: &_observation obstype: category: data multiple: true defaults: - context: _verb: [retrieve] type: [ob] vals: [1] type: enum values: "obstype.yaml" # TODO : Migration from old images to new images range: category: data type: any latitude: category: data type: any longitude: category: data type: any # type: [im] # obstype: [=0 %and (ident=52 %or ident=53 %or ident=54)) %then # %warning "replacing obstype=0 by channel=2, instrument=205" # %unset obstype # %set channel = 2 # %set instrument = 205 # %if (type=im %and obstype=10 %and (ident=52 %or ident=53 %or ident=54)) %then # %warning "replacing obstype=10 by channel=3, instrument=205" # %unset obstype # %set channel = 3 # %set instrument = 205 # %if (type=im %and obstype=20 %and (ident=52 %or ident=53 %or ident=54)) %then # %warning "replacing obstype=10 by channel=1, instrument=205" # %unset obstype # %set channel = 1 # %set instrument = 205 # # goes # %if (type=im %and obstype=0 %and (ident=252 %or ident=253 %or ident=254 %or ident=255 %or ident=256)) %then # %warning "replacing obstype=0 by channel=4, instrument=615" # %unset obstype # %set channel = 4 # %set instrument = 615 # %if (type=im %and obstype=10 %and (ident=252 %or ident=253 %or ident=254 %or ident=255 %or ident=256)) %then # %warning "replacing obstype=10 by channel=1, instrument=615" # %unset obstype # %set channel = 1 # %set instrument = 615 # %if (type=im %and obstype=20 %and (ident=252 %or ident=253 %or ident=254 %or ident=255 %or ident=256)) %then # %warning "replacing obstype=20 by channel=3, instrument=615" # %unset obstype ####################################################################### _postproc: &_postproc accuracy: category: postproc flatten: false type: [enum, integer] values: - [av, archived value] - ['n', normal, auto] - [r, reduced] - [l, low] bitmap: category: postproc flatten: false type: any format: category: postproc flatten: false type: enum values: - [grib1, grib, gb, grib edition 1] - [grib2, grib edition 2] - [bufr, bf] - [grid, gd] - [netcdf] - [odb] - [ascii] - [p, packed] - [u, unpacked] frame: category: postproc type: integer gaussian: category: postproc type: enum values: - reduced - regular area: category: postproc flatten: false multiple: true type: [float, enum] values: - [g, global] - [e, europe] grid: category: postproc flatten: false multiple: true type: [enum, regex, float] values: - auto - [av, archived value] - [F16, 16] - [F24, 24] - [F32, 32] - [F48, 48] - [F64, 64] - [F80, 80] - [F96, 96] - [F128, 128] - [F160, 160] - [F192, 192] - [F200, 200] - [F256, 256] - [F320, 320] - [F400, 400] - [F512, 512] - [F576, 576] - [F640, 640] - [F800, 800] - [F912, 912] - [F1024, 1024] - [F1280, 1280] - [F1600, 1600] - [F2000, 2000] - [F2560, 2560] - [F4000, 4000] - [F8000, 8000] regex: - '^[oOfF][1-9][0-9]*$' - '^[nN](32|48|64|80|96|128|160|200|256|320|400|512|640|800|1024|1280|8000)$' - '^[hH][rRnN]?(1|2|4|8|16|32|64|128|256|512|1024|2048|4096|8192)$' uppercase: true interpolation: category: postproc flatten: false type: enum values: - [linear] - [bilinear] - [nearest-lsm, nlsm, nearest lsm] - [nearest-neighbour, nn, nearest neighbour] - [grid-box-average, average] packing: category: postproc flatten: false type: enum values: - [so, second order] - [av] - [complex, co] - [simple, si] - [ccsds] resol: category: postproc flatten: false type: [enum, integer] values: - [av, archived value] - [auto, automatic resolution] - [N128, reduced gaussian 128] - [N200, reduced gaussian 200] rotation: category: postproc flatten: false multiple: true type: float intgrid: category: postproc flatten: false type: [enum, regex] values: - auto - N32 - N48 - N64 - N80 - N96 - N128 - N160 - N192 - N200 - N256 - N320 - N400 - N512 - N640 - N800 - N912 - N1024 - N1280 regex: - '^[oOfFhH][1-9][0-9]+$' truncation: category: postproc flatten: false type: [enum, integer] values: - auto - none process: category: postproc flatten: false type: enum values: - local - server ####################################################################### _obspproc: &_obspproc filter: type: any category: postproc ident: type: any category: postproc ####################################################################### disseminate: <<: *_field <<: *_postproc requirements: type: any resol: category: postproc type: any # repres: # category: postproc # type: any day: category: postproc multiple: true type: to-by-list by: 1 range: [1, 31] use: category: sink flatten: false multiple: true type: enum values: # - [frequent, f] # - [infrequent, i] # - [normal, n] # - compare # - [monthly run] # - intent # - disk - [bc, boundary conditions] - [monday, mon] - [tuesday, tue] - [wednesday, wed] - [thursday, thu] - [friday, fri] - [saturday, sat] - [sunday, sun] option: category: sink default: normal flatten: false multiple: true type: enum values: - normal - delay - asap - gts - opendata compatibility: category: postproc flatten: false multiple: true type: enum values: - 'no-local-extension' - 'adjust-spectral-packing' priority: category: sink flatten: false type: integer target: category: sink flatten: false type: any filename: category: sink flatten: false type: any ############################################################## archive: <<: *_field <<: *_observation resol: category: postproc type: any # repres: # category: postproc # type: any database: flatten: false multiple: true type: any # TODO set source: category: sink flatten: false multiple: true type: any sourcebase: category: sink flatten: false multiple: true type: any expect: category: sink flatten: false multiple: false type: [enum, integer] values: - any disp: category: sink flatten: false multiple: false type: enum values: - [n, new] - [old] - [remove] - [fail] _clear_defaults: [step] ############################################################## retrieve: _aliases: [r, ret, retr] <<: *_field <<: *_observation <<: *_postproc <<: *_obspproc target: category: sink flatten: false multiple: true type: any source: category: sink flatten: false multiple: true type: any expect: category: sink flatten: false multiple: false type: [enum, integer] values: - any fieldset: category: sink aliases: [field] flatten: false multiple: false type: any database: category: sink flatten: false multiple: true aliases: [dbase] type: any optimise: category: sink type: enum values: - 'on' - 'off' defaults: - vals: ["off"] duplicates: category: sink defaults: - context: _verb: [retrieve] type: [ob] vals: [keep] type: enum values: - keep - remove padding: category: sink flatten: false type: enum defaults: - context: _verb: [retrieve] class: [ti] vals: [0] values: - [0, none, n] - [auto, automatic] ############################################################## read: source: category: sink flatten: false multiple: true type: any <<: *_field <<: *_observation <<: *_postproc <<: *_obspproc target: category: sink flatten: false multiple: true type: any fieldset: category: sink aliases: [field] flatten: false multiple: false type: any _clear_defaults: [class, date, domain, expver, levelist, levtype, param, step, stream, time, type] _options: param: # expand_with: # In case not type/stream/levtype is provided # type: an # stream: oper # levtype: pl first_rule: true ############################################################## flush: <<: *_field <<: *_observation <<: *_postproc <<: *_obspproc wait: flatten: false multiple: false type: enum values: - [true, yes, y, on, 1] - [false, no, n, off, 0] decache: flatten: false multiple: false type: enum values: - [true, yes, y, on, 1] - [false, no, n, off, 0] _clear_defaults: [class, date, domain, expver, levelist, levtype, param, step, stream, time, type] ############################################################## get: tape: category: sink flatten: false multiple: false type: any database: category: sink flatten: false multiple: true type: any target: category: sink flatten: false multiple: true type: any ############################################################## list: <<: *_field <<: *_observation database: category: sink flatten: false multiple: true type: any target: category: sink flatten: false multiple: true type: any pseudodate: flatten: false multiple: false type: enum values: - [latest] - [earliest] output: category: sink flatten: false multiple: false defaults: - vals: [table] type: enum values: - [table] - [browse] - [cost] - [search] - [tree] - [json] _clear_defaults: [date, domain, expver, levelist, levtype, param, step, stream, time, type] _multiple: [class, expver, stream, type] ############################################################## compute: formula: flatten: false multiple: false type: any fieldset: category: sink aliases: [field] flatten: false multiple: false type: any ############################################################## write: fieldset: category: sink aliases: [field] flatten: false multiple: false type: any target: category: sink flatten: false multiple: true type: any ############################################################## pointdb: lat: multiple: false type: float lon: multiple: false type: float <<: *_field _clear_defaults: [class, date, domain, expver, levelist, levtype, param, step, stream, time, type] _options: param: # expand_with: # In case not type/stream/levtype is provided # type: an # stream: oper # levtype: pl first_rule: true end: {} metkit-1.16.0/share/metkit/make-params-yaml.py000066400000000000000000000047731513171467200212250ustar00rootroot00000000000000# (c) Copyright 1996-2012 ECMWF. # # This software is licensed under the terms of the Apache Licence Version 2.0 # which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. # In applying this licence, ECMWF does not waive the privileges and immunities # granted to it by virtue of its status as an intergovernmental organisation nor # does it submit to any jurisdiction. # Documentation is available on Confluence # https://confluence.ecmwf.int/display/METK/MetKit+configuration import os import sys from collections import OrderedDict import psycopg2 import yaml DEFAULT_PORT = 5432 def main(): try: HOST = os.environ['PRODUCT_CATALOGUE_HOST'] DB = os.environ['PRODUCT_CATALOGUE_DB'] USER = os.environ['PRODUCT_CATALOGUE_USER'] PASSWORD = os.environ['PRODUCT_CATALOGUE_PASSWORD'] PORT = ( int(os.environ['PRODUCT_CATALOGUE_PORT']) if 'PRODUCT_CATALOGUE_PORT' in os.environ else DEFAULT_PORT ) except KeyError as e: print("ERROR: Environment variable not found: {}".format(e)) sys.exit(1) with psycopg2.connect(host=HOST, dbname=DB, user=USER, password=PASSWORD, port=PORT) as conn: with conn.cursor() as cur: cur.execute( "SELECT DISTINCT class, stream, type, levtype, param::INTEGER FROM fields WHERE param != '' ORDER BY class, stream, type, levtype, param::INTEGER" ) rows = cur.fetchall() index = OrderedDict() for row in rows: cl, stream, type_, levtype, param = row key = (cl, stream, type_, levtype) if key not in index: index[key] = [] index[key].append(param) # Manually add type=tf parameters for PGEN index[("od", "oper", "tf", "")] = [129, 999] index[("od", "scda", "tf", "")] = [129, 999] index[("od", "enfo", "tf", "")] = [129, 999] yaml_dump_data = [] for key, vals in sorted(index.items()): if key[3]: yaml_dump_data.append( [{"class":key[0], "stream":key[1], "type":key[2], "levtype":key[3]}, vals] ) else: yaml_dump_data.append([{"class":key[0], "stream":key[1], "type":key[2]}, vals]) with open("params.yaml", "w") as f: f.write( "# File automatically generated by %s\n# Do not edit\n\n" % (os.path.basename(__file__)) ) f.write(yaml.safe_dump(yaml_dump_data, default_flow_style=False)) if __name__ == "__main__": main() metkit-1.16.0/share/metkit/make-yaml.py000077500000000000000000000115441513171467200177410ustar00rootroot00000000000000#!/usr/bin/env python3 # (c) Copyright 1996-2012 ECMWF. # # This software is licensed under the terms of the Apache Licence Version 2.0 # which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. # In applying this licence, ECMWF does not waive the privileges and immunities # granted to it by virtue of its status as an intergovernmental organisation nor # does it submit to any jurisdiction. # Documentation is available on Confluence # https://confluence.ecmwf.int/display/METK/MetKit+configuration import mysql.connector import yaml import re import os connectionDetails = dict( host = "webapps-db-prod", user = os.environ['PARAM_DB_USER'], passwd = os.environ['PARAM_DB_PASSWORD']) def execute(database, fun, prefix=None, asList=False, lowercase=True): connection = mysql.connector.connect(**connectionDetails) cursor = connection.cursor() cursor.execute("USE " + database) r = fun(cursor, prefix, asList, lowercase) if (prefix) else fun(cursor) cursor.close() connection.close() return r ################################################################################################ def ids(cursor, prefix, asList, lowercase): PRODGEN = {} if os.path.exists("prodgen-" + prefix + "ids.yaml"): with open("prodgen-" + prefix + "ids.yaml") as f: PRODGEN = yaml.load(f.read(), Loader=yaml.FullLoader) IDS = {} if os.path.exists(prefix + "ids.yaml"): with open(prefix + "ids.yaml") as f: IDS = yaml.load(f.read(), Loader=yaml.FullLoader) if asList: # Convert list of lists to dictionary IDS = {item[0]: item[1:] for item in IDS} cursor.execute("select * from " + prefix) for data in cursor.fetchall(): paramid, abbr, longname = int(data[0]), data[1], data[2] if lowercase: abbr = abbr.lower() abbr = re.sub(r"\W", "_", abbr) abbr = re.sub(r"_+", "_", abbr) abbr = re.sub(r"^_", "", abbr) abbr = re.sub(r"_$", "", abbr) if not abbr: abbr = "_%s_%06d" % (prefix, paramid,) entry = [abbr.strip(), longname.strip()] if paramid in PRODGEN: pgen = [str(x).lower() for x in PRODGEN[paramid]] p = [] for n in pgen: if ( n not in entry ): # and (' ' not in n) and ('.' not in n): # and ('-' not in n): entry.append(n) p.append(n) entry = tuple(entry) if entry[0].lower() == entry[1].lower(): entry = tuple([entry[0]]) else: entry = tuple(entry) if paramid in IDS: before = tuple(IDS[paramid]) if before != entry: print( "WARNING! updated {}id: {}, {} => {}".format(prefix, paramid, before, entry) ) IDS[paramid] = list(entry) else: print("new {}id: {} {}".format(prefix, paramid, entry)) IDS[paramid] = list(entry) for paramid, entry in PRODGEN.items(): if paramid not in IDS: print("WARNING! adding pseudo-{}id: {}, {}".format(prefix, paramid, tuple(entry))) IDS[paramid] = entry if asList: # Sort by key and convert to list of lists return [[k] + v for k, v in sorted(IDS.items(), key=lambda item: item[0])] return IDS ################################################################################################ def getListOfRT(cursor, group_id): def sorted(cursor): cursor.execute("SELECT code FROM odbadmin_reporttype WHERE group_id = " + str(group_id)) r = [r[0] for r in cursor.fetchall()] r.sort() return r return sorted(cursor) T = """- context:\n type: [ofb,mfb,oai,sfb,fsoifb,fcdfb,ofa]\n obsgroup: [%(OBSGROUP)s]\n defaults:\n reportype: [%(REPORTYPE_LIST)s]\n""" def reportype(cursor): cursor.execute("SELECT id,marsname FROM odbadmin_group") GROUP = dict([(r[0],str(r[1]).lower()) for r in cursor.fetchall()]) cursor.execute("SELECT DISTINCT group_id FROM odbadmin_reporttype ORDER BY group_id") groups = [r[0] for r in cursor.fetchall()] def expand(g): return T % dict(OBSGROUP = GROUP[g], REPORTYPE_LIST = "/".join([str(r) for r in getListOfRT(cursor, g)])) return "\n".join([expand(group_id) for group_id in groups]) ################################################################################################ def header(f,o): f.write( "---\n# File automatically generated by %s --%s\n# Do not edit\n\n" % (os.path.basename(__file__), o) ) options = 'chem param reportype'.split() def main(): import sys opts = sys.argv[1:] if len(opts) != 1 or opts[0].lstrip('-') not in options: print(sys.argv[0] + ": Possible options: --" + ", --".join(options)) sys.exit(1) o = opts[0].lstrip('-') match o: case 'chem': content = execute("param", ids, o, True, False) with open(o + "ids.yaml", "w") as f: header(f, o) yaml.safe_dump(content, f, default_flow_style=None) case 'param': content = execute("param", ids, o) with open(o + "ids.yaml", "w") as f: header(f, o) yaml.safe_dump(content, f, default_flow_style=False) case 'reportype': with open("reportype.yaml", "w") as f: header(f, o) f.write(execute("odbgov", reportype)) if __name__ == "__main__": main() metkit-1.16.0/share/metkit/modifiers.yaml000066400000000000000000000151371513171467200203560ustar00rootroot00000000000000--- - context: _verb: [list] output: ['!', browser] class: 'undefined' set: class: [od] # type = ob is already the default && stream comes after type in axis order # - context: # _verb: [retrieve] # stream: [ssmi] # set: # type: [ob] - context: _verb: [list] output: ['!', browser] class: ['!', rd'] defaults: type: [an] stream: [oper] expver: [0001] - context: _verb: [list] output: ['!', browser] class: ['!', rd] pseudodate: 'undefined' defaults: date: [-1] - context: _verb: [list] output: ['!', browser] class: [rd] expver: 'undefined' error: "Missing expver. Please, specify one" - context: class: [ti] defaults: stream: [enfo] - context: class: ['!', ti] defaults: stream: [oper] - context: _verb: [retrieve] stream: [ssbt, e1, ssmi] set: stream: [oper] warn: "Changed stream=oper" - context: class: [ti] type: [fc] set: stream: [oper] - context: class: [ti, s2, ur, rr, lw] expver: 'undefined' set: expver: [prod] - context: class: [ml, ur, rr] unset: [model] - context: _verb: [retrieve] class: [ai] defaults: model: [aifs-single-mse] - context: class: ['!', d1] dataset: ['!', on-demand-extremes-dt] unset: [georef] - context: type: ['!', oldim, ob, fb, ai, af, ab, tf, ofb, mfb, oai, sfb, fsoifb, fcdfb, ofa] unset: [obsgroup, obstype, duplicates] - context: stream: ['!', ssmi] type: [im, sim, oldim] unset: [levtype, levelist, param, grid, rotation, duplicates] - context: type: [ssd, mpp, gsd, ob, fb, ai, af, ab, ofb, mfb, oai, sfb, fsoifb, fcdfb, ofa] unset: [levtype] - context: stream: [ssmi] unset: [levtype, levelist, param, grid, rotation] # new default for levtype=ml, to be enabled later # - context: # levtype: [ml] # defaults: # levelist: [1, 2] - context: levtype: [ml, pl] defaults: levelist: [1000, 850, 700, 500, 400, 300] - context: type: [ssd, mpp, gsd, ob, fb, ai, af, ab, ofb, mfb, oai, sfb, fsoifb, fcdfb, tf, ofa] unset: [levelist] - context: levtype: [o2d, sfc, wave, al] unset: [levelist] - context: class: [er] levtype: [o3d] unset: [levelist] - context: section: [m, z] product: [inst, tacc, tavg] levtype: [dp] unset: [levelist] - context: section: [v] product: [tims] levtype: [dp] unset: [levelist] - context: type: [ob, fb, ai, af, ab, ofb, mfb, oai, sfb, fsoifb, fcdfb, tf, ofa] unset: [param] - context: stream: [mfhm] type: [em, es, ses] unset: [date] - context: stream: [mnfh] type: [em, es, ses, ed] unset: [date] - context: stream: [clmn] unset: [date] - context: stream: ['!', enfh, enwh, efho, ehmm, ewho, eefh, weeh, efrf, wfrf, efsr, wfsr, wfcl, efcl] unset: [hdate] - context: class: [dm] type: [fc] set: time: [0] - context: type: [ab] unset: [time] - context: stream: [clmn, dame, mdfa] unset: [time] - context: class: ['!', er] stream: [moda, msda, edmo, ewmo, wamd] unset: [time] - context: class: ['!', to, dt] unset: [leadtim, opttime] - context: stream: ['!', seap] unset: [leadtime, opttime] - context: stream: ['!', ssmi] type: [im, oldim] unset: [step] - context: stream: [ssmi, mnfm, mfhm, mfam, mfwm, mhwm, esmm, ehmm, mawm, dame, sfmm, swmm, smma, mmsa] unset: [step] - context: type: [gsd, ob, fb, ai, af, ab, ofb, mfb, oai, sfb, fsoifb, fcdfb, cl, ofa] unset: [step] - context: class: ['!', er] stream: [moda, msda, edmo, ewmo, wamd] unset: [step] - context: class: [ed,ng] unset: [step] - context: class: [d1] dataset: [climate-dt] unset: [step] - context: stream: ['!', lwda, lwwv, elda, ewla, wfas, wfcl, wfse, wfrf, wfsr, efas, efcl, efse, efrf, efsr] unset: [anoffset] - context: stream: [efas, efcl, efse, efrf, efsr, wfas, wfcl, wfse, wfrf, wfsr] type: ['!', go, sfo, fu] unset: [anoffset] - context: class: [ti, s2] type: [cf] defaults: number: [0] - context: type: ['!', pf, cm, cs, cr, cv, sv, as, fp, ed, tu, ci, me, ff, icp, sot, fcmean, fcmax, fcmin, fcstdev, svar, gwt, bf, wp] class: ['!', ti, lw, s2] stream: ['!', mofc, wamf, mofm, wmfm, seas, wasf, wamf, sfmm, smma, seap, swmm, ocea, mnfc, mnfh, mnfa, mnfw, mfhw, mfaw, mnfm, mfhm, mfam, mfwm, mhwm, mawm, mmsf, msmm, wams, mswm, mmsa, enda, ewda, edmm, edmo, ewmm, ewmo, elda, ewla, espd, mmaf, mmam, mmaw, mmwm, seas, efsr, wfsr, efse, wfse, ocda] unset: [number] - context: _verb: [retrieve, archive] class: ['!', ti, s2] type: [cf, em, es, ses, taem, taes] stream: ['!', mofc, wamf, mofm, wmfm] unset: [number] - context: type: ['!', pd, cd, pb, taem, pfc] unset: [quantile] - context: class: ['!', d1, ed, ng, ms] defaults: domain: [g] - context: class: [od] type: [cm, cs, cr] domain: [g] set: domain: [e] - context: class: [ep] levtype: [o2d, o3d] unset: [domain] - context: class: [d1, ng, ti, s2, ur, lw, rr, ed] unset: [domain] - context: type: ['!', im, sim, oldim, ob, fb, ai, af, ab, tf, ofb, mfb, ssd, oai, gsd, sfb, fsoifb, fcdfb, ofa] unset: [ident] - context: class: [ci, dt] unset: [method] - context: class: [ti, s2] defaults: origin: [ecmf] - context: class: ['!', od, en, me, c3, ci] unset: [system] - context: accuracy: ['n'] unset: [accuracy] - context: accuracy: [l, r] set: accuracy: [8] - context: format: [p] unset: [format] - context: area: [e] set: area: [73.5,-27,33,45] - context: grid: [av] unset: [grid] - context: type: [ai, ob, fb, af, ab, ofb, mfb, oai, sfb, fsoifb, fcdfb, tf, ofa] unset: [grid, rotation] - context: style: [dissemination] set: resol: [av] warn: "Force resol=av when style=dissemination" - context: style: [dissemination] resol: [auto] set: resol: [av] warn: "Force resol=av when style=dissemination" - context: resol: [av] set: intgrid: [source] truncation: [none] - context: resol: [N128,N200] set: intgrid: _resol - context: resol: ['!',av,auto,N128,N200] set: truncation: _resol - context: _verb: [retrieve] class: [ti] defaults: process: [local] - context: _verb: [retrieve] source: 'defined' defaults: database: [file] - context: obsgroup: 'defined' defaults: duplicates: [keep] - context: obstype: 'defined' defaults: duplicates: [keep] - context: _verb: [retrieve] class: [ti] defaults: padding: [0] - context: class: [ms] country: [it] defaults: grib: [ecmwf] metkit-1.16.0/share/metkit/obstype.yaml000066400000000000000000000162761513171467200200670ustar00rootroot00000000000000--- - name: all group: - name: [nsd, conv, conventional, non satellite data all] group: - name: [lsd, land surface data] group: - [1, s, synop land] - [2, s2, synop record 2 land] - [3, sa, synop auto land] - [4, sa2, synop auto record 2 land] - [7, set, soil and earth temperature] - [28, snowd, snow depth] - [140, metar] - [147, ametar, auto metar] - [165, snow, imssnow, snowcover, snow cover] - [170, bs, bufr land synop] - [172, bs2, bufr land synop 2] - [176, bsr6, bufr land synop wmo region 6] - [178, bs1h, bufr land synop 1 hourly] - name: [ssd, sea surface data] group: - [9, sab, synop abbreviated ship] - [11, ss, synop ship] - [12, ss2, synop record 2 ship] - [13,sas, synop auto ship] - [14, sas2, synop auto record 2 ship] - [19, sh, shred] - [21, dsu, dribu surface] - [22, bsu, bathy surface] - [23, tsu, tesac surface] - [26, ostia] - [27, buoy] - [180, bss, bufr ship synop] - [181, bmb, bufr moored buoys] - [182, bdb, bufr drifting buoys] - name: [vsns, vertical soundings not satellite] group: - [91, p, pilot land] - [92, ps, pilot ship] - [95, wp, wind profile] - [96, ewp, european wind profile] - [97, ewtp, european wind and temperature profile] - [101, t, temp land] - [102, ts, temp ship] - [103, td, temp drop] - [104, r, rocob land] - [105, rs, rocob ship] - [106, tm, temp mobile] - [107, ct, climate temp] - [109, hrt, high resolution temp land] - [111, hrts, high resolution temp ship] - [112, bp, bufr land pilot] - [113, bps, bufr ship pilot] - [230, btd, bufr temp drop] - [231, btdc, bufr temp descent] - name: [slns, single level upper air not satellite] group: - [141, cod, codar] - [142, air, airep] - [143, col, colba] - [144, am, amdar] - [145, ac, acars] - [146, eam, e-amdar] - [149, acmr, acars with mixing ratio] - name: [sls, single level upper air satellite] group: - [82, sat2, satob section 2] - [83, sat3, satob section 3] - [84, sat4, satob section 4] - [85, sat5, atob section 5] - [86, sat6, high resolution winds] - [87, sat7, high density unified format satellite winds] - [88, geor, geostationary radiances] - [89, gcsr, geostationary clear sky radiances] - [189, gmsgr, geostationary msg radiances] - [190, gasr, geostationary all sky radiances] - name: [od, oceanographic data] group: - [131, do, dribu oceanographic] - [132, bo, bathy oceanographic] - [133, to, tesac oceanographic] - [184, argo, bufr argo] - name: [dd, derived data] group: - [164, pa, paobs] - [237, bice, baltic_ci, baltic sea ice] - name: [cc, chemical constituent] group: # - [157, so, surface ozone] # - [158, soa, surface ozone averaged] - [162, ovs, ozone vertical sounding] - [159, op, ozone partial] - name: [sf, synoptic features] group: - [31, stor, storm] - [32, tc, tropical cyclone] # ???? - [110, pgps, gbgps, ground based gps] - name: [sd, satellite data all] group: - name: [sds, ers1, surface data satellite] group: - [121, was, wavescat, wave scatterometer] - [122, wis, scat, wind scatterometer] - [123, ral, ralt, radar altimeter] - [124, sst, sea surface temperature] - [210, esar, wavesar, envisat sar] - [212, emeris, envisat_meris, envisat meris] - [213, era, envisat radar altimeter] - [214, jra, jason radar altimeter] - [216, j2ra, jason2 radar altimeter] - [217, cryora, cryosat-2 radar altimeter] - [218, saral, saral radar altimeter] - name: [vss, vertical soundings satellite] group: - [51, hr, high resolution] - [53, rtov, fbtovs, tovh, rtovs] - [54, tovb, tovs1b] - [55, atov, atovs] - [56, atop, atovs products] - [57, airs, fbairs] - [59, amsre, fbamsre, advanced microwave scanning radiometer] - [60, amsr2, amsr2_gc, advanced microwave scanning radiometer 2] # ???? - [61, smt, satem mean temperature] - [62, sw, satem water] - [63, shl, satem higher level] - [65, slm, satem levels merged] - [71, mt, mean temperature] - [72, w, water] - [73, hl, higher level] - [75, tlm, tovs levels merged] - [138, oscat] - [139, ascat] - [153, mwribt, micro wave radiation imager] - [155, ateu, amsu_ears, atovs eumetsat] - [211, saphir] - [240, iasi, fbiasi, iasi_screened] # ???? - [250, gpsro, fbgpsro, gps radio occultation] - [126, ssmi, microwave images] - [49, ssmis, fbssmis, special sensor microwave imager sounder] - [127, ssbt, fbssmi, sea surface brigthness temperature] - name: trmm group: - [129, tbt, fbtmi, tmi brightness temperatures] - [130, ti3r, tmi instantaneous 3-d rainfall structure] - name: qscat group: - [137, qsca, quikscat] - [138, qssw, quikscat seawinds] - name: reo3 group: - [206, reo3, fbreo3, ozone] - [207, modis, modis aerosol] - [208, limd, layer integrated mass density] - [209, limd_ak, layer integrated mass density with averaging kernels] - [156, wsat, fbwindsat, windsat] - [154, vass, vertical atmospheric sounder system] - [201, atms, advanced technology microwave sounder] - [202, cris, cross-track infrared sounder ] - [252, giirs] - [245, hiras2] - [246, aws] - name: bufr group: [1, 3, 9, 11, 13, 19, 21, 22, 23, 28, 61, 62, 63, 82, 83, 84, 85, 86, 87, 91, 92, 95, 96, 101, 102, 103, 106, 110, 109, 111, 112, 113, 140, 142, 143, 144, 145, 146, 147, 149, 164, 170, 172, 176, 178, 180, 230, 231] - name: fbconv group: [1, 3, 9, 11, 13, 19, 21, 22, 23, 28, 65, 82, 83, 86, 87, 91, 92, 95, 96, 101, 102, 103, 106, 110, 140, 142, 143, 144, 145, 164] - name: fbscat group: [122, 136, 137, 139] - name: fbrad1c group: [54, 55] - name: fbgeos group: [89, 189, 190] - [255, fbtrmr] - [125, rw, nexrad, nexrad_rr, reprocessed wind] - [224, gbt, gpm, gmi brightness temperatures] - name: grad group: [88, 89, 189, 190] - [203, smos] - [204, smap] - name: dmbo group: [181, 182] - [251, aeolus]metkit-1.16.0/share/metkit/odb/000077500000000000000000000000001513171467200162465ustar00rootroot00000000000000metkit-1.16.0/share/metkit/odb/CMakeLists.txt000066400000000000000000000007131513171467200210070ustar00rootroot00000000000000list( APPEND files_odb marsrequest.yaml class.table type.table stream.table group.txt ) foreach( _file ${files_odb} ) configure_file( ${_file} ${CMAKE_BINARY_DIR}/share/metkit/odb/${_file} COPYONLY ) if( HAVE_METKIT_CONFIG ) install( FILES ${CMAKE_BINARY_DIR}/share/metkit/odb/${_file} DESTINATION "share/metkit/odb" PERMISSIONS OWNER_WRITE OWNER_READ GROUP_READ WORLD_READ ) endif() endforeach() metkit-1.16.0/share/metkit/odb/class.table000066400000000000000000000035531513171467200203720ustar00rootroot000000000000000 0 Unknown 1 od Operational archive 2 rd Research department 3 er 15 years reanalysis (ERA15) 4 cs ECSN 5 e4 40 years reanalysis (ERA40) 6 dm DEMETER 7 pv PROVOST 8 el ELDAS 9 to TOST 10 co COSMO-LEPS 11 en ENSEMBLES 12 ti TIGGE 13 me MERSEA 14 ei ERA Interim 15 sr Short-Range Ensemble Prediction System 16 dt Data Targeting System 17 la ALADIN-LAEF 18 yt YOTC 19 mc Copernicus Atmosphere Monitoring Service (CAMS, previously MACC) 20 pe Permanent experiments 21 em ERA-CLIM model integration for the 20th-century (ERA-20CM) 22 e2 ERA-CLIM reanalysis of the 20th-century using surface observations only (ERA-20C) 23 ea ERA5 24 ep ERA-CLIM2 coupled reanalysis of the 20th-century (CERA-20C) 25 rm EURO4M 26 nr NOAA/CIRES 20th Century Reanalysis version II 27 s2 Sub-seasonal to seasonal prediction project (S2S) 28 j5 Japanese 55 year Reanalysis (JRA55) 29 ur UERRA 30 et ERA-CLIM2 coupled reanalysis of the satellite era (CERA-SAT) 31 c3 Copernicus Climate Change Service (C3S) 32 yp YOPP 33 l5 ERA5/LAND 34 lw WMO Lead Centre Wave Forecast Verification 35 ce Copernicus Emergency Management Service (CEMS) 36 cr Copernicus Atmosphere Monitoring Service (CAMS) Research 37 rr Copernicus Regional ReAnalysis (CARRA/CERRA) 38 ul Project ULYSSES 39 gw Global Wildfire Information System 40 e6 ERA6 41 l6 ERA6/LAND 42 ef EFAS (European flood awareness system) 43 gf GLOFAS (Global flood awareness system) 44 gg Greenhouse Gases 45 ml Machine learning 46 d1 Destination Earth 47 o6 Ocean ReAnalysis 6 53 ng nextGEMS project 99 te Test 100 at Austria 101 be Belgium 102 hr Croatia 103 dk Denmark 104 fi Finland 105 fr France 106 de Germany 107 gr Greece 108 hu Hungary 109 is Iceland 110 ie Ireland 111 it Italy 112 nl Netherlands 113 no Norway 114 pt Portugal 115 si Slovenia 116 es Spain 117 se Sweden 118 ch Switzerland 119 tr Turkey 120 uk United Kingdom 121 ms Member States projects 199 ma Metaps metkit-1.16.0/share/metkit/odb/group.txt000066400000000000000000000110531513171467200201430ustar00rootroot00000000000000 id↑ ; name ; kind_id ; marsname ; description ; 1 ; HIRS ; 2 ; HIRS ; ; 2 ; AMSUA ; 2 ; AMSUA ; ; 3 ; AMSUB ; 2 ; AMSUB ; ; 4 ; MHS ; 2 ; MHS ; ; 5 ; GEOS ; 2 ; GEOS ; ; 6 ; RESAT ; 2 ; RESAT ; ; 7 ; MERIS ; 2 ; MERIS ; ; 8 ; GPSRO ; 2 ; GPSRO ; ; 9 ; SATOB ; 3 ; SATOB ; ; 10 ; SCATT ; 2 ; SCATT ; ; 11 ; SSMI All-sky ; 2 ; SSMI_AS ; ; 12 ; IASI ; 2 ; IASI ; ; 13 ; AIRS ; 2 ; AIRS ; ; 14 ; SSMIS All-sky ; 2 ; SSMIS_AS ; ; 15 ; TMI All-sky ; 2 ; TMI_AS ; ; 16 ; AMSRE All-sky ; 2 ; AMSRE_AS ; ; 17 ; CONV ; 1 ; CONV ; ; 18 ; STORM ; 1 ; STORM ; STORM ; 19 ; SMOS ; 2 ; SMOS ; ; 20 ; WINDSAT All-sky ; 2 ; WINDSAT_AS ; ; 21 ; SSMI ; 2 ; SSMI ; ; 22 ; AMSUA All-sky ; 2 ; AMSUA_AS ; ; 23 ; AMSRE ; 2 ; AMSRE ; ; 24 ; TMI ; 2 ; TMI ; ; 25 ; SSMIS ; 2 ; SSMIS ; ; 26 ; GBRAD ; 1 ; GBRAD ; ; 27 ; MWHS ; 2 ; MWHS ; ; 28 ; MWTS ; 2 ; MWTS ; ; 29 ; MWRI All-sky ; 2 ; MWRI_AS ; ; 30 ; IRAS ; 2 ; IRAS ; ; 31 ; MSU ; 2 ; MSU ; ; 32 ; SSU ; 2 ; SSU ; ; 33 ; VTPR1 ; 2 ; VTPR1 ; ; 34 ; VTPR2 ; 2 ; VTPR2 ; ; 35 ; ATMS ; 2 ; ATMS ; ; 36 ; RESAT Averaging Kernels ; 2 ; RESAT_AK ; ; 37 ; CRIS ; 2 ; CRIS ; Cross-track Infrared Sounder ; 38 ; WAVE integrated Parameters ; 3 ; WAVE_IP ; WAVE integrated Parameters ; 39 ; WAVE spectra ; 3 ; WAVE_SP ; WAVE spectra ; 40 ; RAINGG ; 5 ; RAINGG ; Rain Gauge ; 41 ; SURFACE MULTISENSOR ; 1 ; SFC_MS ; SURFACE MULTISENSOR ; 42 ; AMSR-2 All-sky ; 2 ; AMSR2_AS ; AMSR-2 All-sky ; 43 ; SAPHIR All-sky ; 2 ; SAPHIR_AS ; SAPHIR All-sky ; 44 ; AMSUB All-sky ; 2 ; AMSUB_AS ; AMSUB All-sky ; 45 ; MHS All-sky ; 2 ; MHS_AS ; MHS All-sky ; 46 ; Doppler Wind Lidar ; 2 ; DWL ; Doppler Wind Lidar ; 47 ; IRIS ; 2 ; IRIS ; Infrared Interferometer Spectrometer ; 48 ; Altimeter ; 3 ; ALT ; Altimeter ; 49 ; AATSR ; 2 ; AATSR ; Advanced Along Track Scanning Radiometer ; 50 ; ATMS All-sky ; 2 ; ATMS_AS ; ATMS All-sky ; 51 ; GMI All-sky ; 2 ; GMI_AS ; GMI All-sky ; 52 ; GODAE Sea Surface Temperatures ; 4 ; GODAE_SST ; GODAE Sea Surface Temperatures ; 53 ; ATOVS MULTISENSOR ; 4 ; ATOVS_MS ; ATOVS MULTISENSOR ; 54 ; Atmospheric composition ; 1 ; ATMOSPHERIC_COMPOSITION ; Atmospheric composition ; 55 ; NON-SURFACE MULTISENSOR ; 4 ; NON_SFC_MS ; NON-SURFACE MULTISENSOR ; 56 ; MWTS2 ; 2 ; MWTS2 ; Microwave Temperature Sounder 2 ; 57 ; SSMI 1DVAR TCWV Cloudy-Sky ; 2 ; SSMI_1D ; SSMI 1DVAR TCWV Cloudy-Sky ; 58 ; MWHS2 All-sky ; 2 ; MWHS2_AS ; Microwave Humidity Sounder 2 ; 59 ; SSMT2 ; 2 ; SSMT2 ; SSMT2 ; 60 ; SMAP ; 2 ; SMAP ; Soil Moisture Active and Passive ; 61 ; TOVS MULTISENSOR ; 4 ; TOVS_MS ; TOVS MULTISENSOR ; 62 ; Cloud reflectivity ; 2 ; CLOUD_R ; Cloud reflectivity ; 63 ; Cloud Lidar ; 2 ; CLOUD_L ; Cloud Lidar ; 64 ; Satellite Lightning ; 2 ; SATELLITE_LIGHTNING ; Satellite Lightning ; 65 ; GEOS VIS ; 2 ; GEOS_VIS ; GEOS visible reflectances ; 66 ; OCONV ; 1 ; OCONV ; Ocean conventional in situ ; 67 ; MWTS3 All-sky ; 2 ; MWTS3_AS ; MWTS3 All-sky ; 68 ; GIIRS ; 2 ; GIIRS ; GIIRS ; 69 ; HIRAS ; 2 ; HIRAS ; HIRAS ; 70 ; TROPICS All-sky ; 2 ; TROPICS_AS ; TROPICS All-sky ; 71 ; SSMT1 ; 2 ; SSMT1 ; SSMT1 ; 72 ; SSMT1 All-sky ; 2 ; SSMT1_AS ; SSMT1 All-sky ; 73 ; MWS All-sky ; 2 ; MWS_AS ; MWS All-sky ; 74 ; MWIICI All-sky ; 2 ; MWIICI_AS ; MWIICI All-sky ; 75 ; AWS All-sky ; 2 ; AWS_AS ; AWS All-sky ; 76 ; LEOS VIS ; 2 ; LEOS_VIS ; LEOS visible reflectances ; 77 ; SSH ; 2 ; SSH ; SSH ; 78 ; SIRS ; 2 ; SIRS ; SIRS ; 79 ; SCR ; 2 ; SCR ; SCR (Selective Chopper Radiometer) ; 80 ; SCAMS All-sky ; 2 ; SCAMS_AS ; SCAMS All-sky ; 81 ; NEMS All-sky ; 2 ; NEMS_AS ; NEMS All-sky ; 82 ; AMSR-3 All-sky ; 2 ; AMSR3_AS ; AMSR-3 All-sky ; 83 ; IRS ; 2 ; IRS ; IRS ; 84 ; IASI-NG ; 2 ; IASI_NG ; IASI-NG ; 85 ; SMAP All-sky ; 2 ; SMAP_AS ; SMAP All-sky ; 86 ; SSMT2 All-sky ; 2 ; SSMT2_AS ; SSMT2 All-sky ; 99 ; TEST ; 4 ; TEST ; ; metkit-1.16.0/share/metkit/odb/marsrequest.yaml000066400000000000000000000001771513171467200215120ustar00rootroot00000000000000--- CLASS: class DATE: andate TIME: antime TYPE: type OBSGROUP: groupid@hdr REPORTYPE: reportype STREAM: stream EXPVER: expver metkit-1.16.0/share/metkit/odb/stream.table000066400000000000000000000113111513171467200205470ustar00rootroot000000000000000 0 Unknown 1022 fsob Forecast sensitivity to observations 1023 fsow Forecast sensitivity to observations wave 1024 dahc Daily archive hindcast 1025 oper Atmospheric model 1026 scda Atmospheric model (short cutoff) 1027 scwv Wave model (short cutoff) 1028 dcda Atmospheric model (delayed cutoff) 1029 dcwv Wave model (delayed cutoff) 1030 enda Ensemble data assimilation 1032 efho Ensemble forecast hindcast overlap 1033 enfh Ensemble forecast hindcasts 1034 efov Ensemble forecast overlap 1035 enfo Ensemble prediction system 1036 sens Sensitivity forecast 1037 maed Multianalysis ensemble data 1038 amap Analysis for multianalysis project 1039 efhc Ensemble forecast hindcasts (obsolete) 1040 efhs Ensemble forecast hindcast statistics 1041 toga TOGA 1042 cher Chernobyl 1043 mnth Monthly means 1044 supd Deterministic supplementary data 1045 wave Wave model 1046 ocea Ocean 1047 fgge FGGE 1050 egrr Bracknell 1051 kwbc Washington 1052 edzw Offenbach 1053 lfpw Toulouse 1054 rjtd Tokyo 1055 cwao Montreal 1056 ammc Melbourne 1057 efas European flood awareness system (EFAS) 1058 efse European flood awareness system (EFAS) seasonal forecasts 1059 efcl European flood awareness system (EFAS) climatology 1060 wfas Global flood awareness system (GLOFAS) 1061 wfcl Global flood awareness system (GLOFAS) climatology 1062 wfse Global flood awareness system (GLOFAS) seasonal forecasts 1063 efrf European flood awareness system (EFAS) reforecasts 1064 efsr European flood awareness system (EFAS) seasonal reforecasts 1065 wfrf Global flood awareness system (GLOFAS) reforecasts 1066 wfsr Global flood awareness system (GLOFAS) seasonal reforecasts 1070 msdc Monthly standard deviation and covariance 1071 moda Monthly means of daily means 1072 monr Monthly means using G. Boer's step function 1073 mnvr Monthly variance and covariance data using G. Boer's step function 1074 msda Monthly standard deviation and covariance of daily means 1075 mdfa Monthly means of daily forecast accumulations 1076 dacl Daily climatology 1077 wehs Wave ensemble forecast hindcast statistics 1078 ewho Ensemble forecast wave hindcast overlap 1079 enwh Ensemble forecast wave hindcasts 1080 wamo Wave monthly means 1081 waef Wave ensemble forecast 1082 wasf Wave seasonal forecast 1083 mawv Multianalysis wave data 1084 ewhc Wave ensemble forecast hindcast (obsolete) 1085 wvhc Wave hindcast 1086 weov Wave ensemble forecast overlap 1087 wavm Wave model (standalone) 1088 ewda Ensemble wave data assimilation 1089 dacw Daily climatology wave 1090 seas Seasonal forecast 1091 sfmm Seasonal forecast atmospheric monthly means 1092 swmm Seasonal forecast wave monthly means 1093 mofc Monthly forecast 1094 mofm Monthly forecast means 1095 wamf Wave monthly forecast 1096 wmfm Wave monthly forecast means 1097 smma Seasonal monthly means anomalies 1110 seap Sensitive area prediction 1120 eefh Extended ensemble forecast hindcast 1121 eehs Extended ensemble forecast hindcast statistics 1122 eefo Extended ensemble prediction system 1123 weef Wave extended ensemble forecast 1124 weeh Wave extended ensemble forecast hindcast 1125 wees Wave extended ensemble forecast hindcast statistics 1200 mnfc Real-time 1201 mnfh Hindcasts 1202 mnfa Anomalies 1203 mnfw Wave real-time 1204 mfhw Monthly forecast hindcasts wave 1205 mfaw Wave anomalies 1206 mnfm Real-time means 1207 mfhm Hindcast means 1208 mfam Anomaly means 1209 mfwm Wave real-time means 1210 mhwm Wave hindcast means 1211 mawm Wave anomaly means 1220 mmsf Multi-model seasonal forecast 1221 msmm Multi-model seasonal forecast atmospheric monthly means 1222 wams Multi-model seasonal forecast wave 1223 mswm Multi-model seasonal forecast wave monthly means 1224 mmsa Multi-model seasonal forecast monthly anomalies 1230 mmaf Multi-model multi-annual forecast 1231 mmam Multi-model multi-annual forecast means 1232 mmaw Multi-model multi-annual forecast wave 1233 mmwm Multi-model multi-annual forecast wave means 1240 esmm Combined multi-model monthly means 1241 ehmm Combined multi-model hindcast monthly means 1242 edmm Ensemble data assimilation monthly means 1243 edmo Ensemble data assimilation monthly means of daily means 1244 ewmo Ensemble wave data assimilation monthly means of daily means 1245 ewmm Ensemble wave data assimilation monthly means 1246 espd Ensemble supplementary data 1247 lwda Long window daily archive 1248 lwwv Long window wave 1249 elda Ensemble Long window Data Assimilation 1250 ewla Ensemble Wave Long window data Assimilation 1251 wamd Wave monthly means of daily means 1252 gfas Global fire assimilation system 1253 ocda Ocean data assimilation 1254 olda Ocean Long window data assimilation 1255 gfra Global Fire assimilation system reanalysis 2231 cnrm Meteo France climate centre 2232 mpic Max Plank Institute 2233 ukmo UKMO climate centre metkit-1.16.0/share/metkit/odb/type.table000066400000000000000000000003541513171467200202420ustar00rootroot00000000000000262 mfb MonDB feedback 263 ofb ODB feedback 264 oai ODB analysis input 265 sfb Summary Feedback 266 fsoifb Forecast Sensitivity to Observations Impact Feedback 267 fcdfb Forecast Departures Feedback 268 ofa ODB Feedback from Analysis metkit-1.16.0/share/metkit/param-matching.yaml000066400000000000000000000011741513171467200212610ustar00rootroot00000000000000# wind families used by ParamID normalisation to retrieve u/v from vo/d and related gradients/anomalies wind: # GRIB2 - [131,132,138,155] - [129131,129132,129138,129155] - [171131,171132,171138,171155] - [200131,200132,200138,200155] # GRIB1 - [131.128,132.128,138.128,155.128] - [131.129,132.129,138.129,155.129] - [131.171,132.171,138.171,155.171] - [131.200,132.200,138.200,155.200] # list of tables used by ParamID normalisation to limit the param-table expansion to wind, ocean and reanalysis drop-tables: [140,150,151,160,162,170,180,190] full-table-dropping: true ml-params-single-level: [22, 127, 128, 129, 152] metkit-1.16.0/share/metkit/paramids.yaml000066400000000000000000016377601513171467200202120ustar00rootroot00000000000000--- # File automatically generated by make-yaml.py --param # Do not edit 1: - strf - Stream function 2: - vp - Velocity potential - vpot 3: - pt - Potential temperature 4: - eqpt - Equivalent potential temperature 5: - sept - Saturated equivalent potential temperature 6: - ssfr - Soil sand fraction 7: - scfr - Soil clay fraction 8: - sro - Surface runoff 9: - ssro - Sub-surface runoff 10: - ws - Wind speed 11: - udvw - U component of divergent wind 12: - vdvw - V component of divergent wind 13: - urtw - U component of rotational wind 14: - vrtw - V component of rotational wind 15: - aluvp - UV visible albedo for direct radiation (climatological) - auvp 16: - aluvd - UV visible albedo for diffuse radiation (climatological) - auvd 17: - alnip - Near IR albedo for direct radiation (climatological) - anip 18: - alnid - Near IR albedo for diffuse radiation (climatological) - anid 19: - uvcs - Clear sky surface UV 20: - parcs - Surface photosynthetically active radiation, clear sky 21: - uctp - Unbalanced component of temperature 22: - ucln - Unbalanced component of logarithm of surface pressure 23: - ucdv - Unbalanced component of divergence 24: - _param_000024 - Reserved for future unbalanced components 25: - _param_000025 - Reserved for future unbalanced components 26: - cl - Lake cover 27: - cvl - Low vegetation cover 28: - cvh - High vegetation cover 29: - tvl - Type of low vegetation 30: - tvh - Type of high vegetation 31: - ci - Sea ice area fraction 32: - asn - Snow albedo 33: - rsn - Snow density 34: - sst - Sea surface temperature - sstk 35: - istl1 - Ice temperature layer 1 36: - istl2 - Ice temperature layer 2 37: - istl3 - Ice temperature layer 3 38: - istl4 - Ice temperature layer 4 39: - swvl1 - Volumetric soil water layer 1 - swv1 40: - swvl2 - Volumetric soil water layer 2 - swv2 41: - swvl3 - Volumetric soil water layer 3 - swv3 42: - swvl4 - Volumetric soil water layer 4 - swv4 43: - slt - Soil type 44: - es - Snow evaporation 45: - smlt - Snowmelt 46: - sdur - Solar duration 47: - dsrp - Surface direct normal short-wave (solar) radiation 48: - magss - Time-integrated magnitude of turbulent surface stress 49: - 10fg - Maximum 10 metre wind gust since previous post-processing 50: - lspf - Large-scale precipitation fraction 51: - mx2t24 - Maximum temperature at 2 metres in the last 24 hours 52: - mn2t24 - Minimum temperature at 2 metres in the last 24 hours 53: - mont - Montgomery potential 54: - pres - Pressure 55: - mean2t24 - Mean temperature at 2 metres in the last 24 hours 56: - mn2d24 - Mean 2 metre dewpoint temperature in the last 24 hours 57: - uvb - Surface downward UV radiation 58: - par - Photosynthetically active radiation at the surface 59: - cape - Convective available potential energy 60: - pv - Potential vorticity 62: - obct - Observation count 63: - stsktd - Start time for skin temperature difference 64: - ftsktd - Finish time for skin temperature difference 65: - sktd - Skin temperature difference 66: - lai_lv - Leaf area index, low vegetation - lailv 67: - lai_hv - Leaf area index, high vegetation - laihv 68: - msr_lv - Minimum stomatal resistance, low vegetation 69: - msr_hv - Minimum stomatal resistance, high vegetation 70: - bc_lv - Biome cover, low vegetation 71: - bc_hv - Biome cover, high vegetation 72: - issrd - Instantaneous surface solar radiation downwards 73: - istrd - Instantaneous surface thermal radiation downwards 74: - sdfor - Standard deviation of filtered subgrid orography (climatological) 75: - crwc - Specific rain water content 76: - cswc - Specific snow water content 77: - etadot - Eta-coordinate vertical velocity - etad 78: - tclw - Total column cloud liquid water 79: - tciw - Total column cloud ice water 80: - _param_000080 - Experimental product 81: - _param_000081 - Experimental product 82: - _param_000082 - Experimental product 83: - _param_000083 - Experimental product 84: - _param_000084 - Experimental product 85: - _param_000085 - Experimental product 86: - _param_000086 - Experimental product 87: - _param_000087 - Experimental product 88: - _param_000088 - Experimental product 89: - _param_000089 - Experimental product 90: - _param_000090 - Experimental product 91: - _param_000091 - Experimental product 92: - _param_000092 - Experimental product 93: - _param_000093 - Experimental product 94: - _param_000094 - Experimental product 95: - _param_000095 - Experimental product 96: - _param_000096 - Experimental product 97: - _param_000097 - Experimental product 98: - _param_000098 - Experimental product 99: - _param_000099 - Experimental product 100: - _param_000100 - Experimental product 101: - _param_000101 - Experimental product 102: - _param_000102 - Experimental product 103: - _param_000103 - Experimental product 104: - _param_000104 - Experimental product 105: - _param_000105 - Experimental product 106: - _param_000106 - Experimental product 107: - _param_000107 - Experimental product 108: - _param_000108 - Experimental product 109: - _param_000109 - Experimental product 110: - _param_000110 - Experimental product 111: - _param_000111 - Experimental product 112: - _param_000112 - Experimental product 113: - _param_000113 - Experimental product 114: - _param_000114 - Experimental product 115: - _param_000115 - Experimental product 116: - _param_000116 - Experimental product 117: - _param_000117 - Experimental product 118: - _param_000118 - Experimental product 119: - _param_000119 - Experimental product 120: - _param_000120 - Experimental product 121: - mx2t6 - Maximum temperature at 2 metres in the last 6 hours 122: - mn2t6 - Minimum temperature at 2 metres in the last 6 hours 123: - 10fg6 - Maximum 10 metre wind gust in the last 6 hours 124: - emis - Surface emissivity 125: - vite - Vertically integrated total energy 126: - _param_000126 - Generic parameter for sensitive area prediction 127: - at - Atmospheric tide 128: - bv - Budget values 129: - z - Geopotential 130: - t - Temperature 131: - u - U component of wind 132: - v - V component of wind 133: - q - Specific humidity 134: - sp - Surface pressure 135: - w - Vertical velocity 136: - tcw - Total column water 137: - tcwv - Total column vertically-integrated water vapour 138: - vo - Vorticity (relative) 139: - stl1 - Soil temperature level 1 - st 140: - swl1 - Soil wetness level 1 141: - sd - Snow depth 142: - lsp - Large-scale precipitation 143: - cp - Convective precipitation 144: - sf - Snowfall 145: - bld - Time-integrated boundary layer dissipation 146: - sshf - Time-integrated surface sensible heat net flux 147: - slhf - Time-integrated surface latent heat net flux 148: - chnk - Charnock - ss 149: - snr - Surface net radiation (SW and LW) 150: - tnr - Top net radiation (SW and LW) 151: - msl - Mean sea level pressure 152: - lnsp - Logarithm of surface pressure 153: - swhr - Short-wave heating rate 154: - lwhr - Long-wave heating rate 155: - d - Divergence 156: - gh - Geopotential height 157: - r - Relative humidity 158: - tsp - Tendency of surface pressure 159: - blh - Boundary layer height 160: - sdor - Standard deviation of sub-gridscale orography 161: - isor - Anisotropy of sub-gridscale orography 162: - anor - Angle of sub-gridscale orography 163: - slor - Slope of sub-gridscale orography 164: - tcc - Total cloud cover 165: - 10u - 10 metre U wind component 166: - 10v - 10 metre V wind component 167: - 2t - 2 metre temperature 168: - 2d - 2 metre dewpoint temperature 169: - ssrd - Surface short-wave (solar) radiation downwards 170: - stl2 - Soil temperature level 2 171: - swl2 - Soil wetness level 2 172: - lsm - Land-sea mask 173: - sr - Surface roughness (climatological) 174: - al - Albedo (climatological) 175: - strd - Surface long-wave (thermal) radiation downwards 176: - ssr - Surface net short-wave (solar) radiation 177: - str - Surface net long-wave (thermal) radiation 178: - tsr - Top net short-wave (solar) radiation 179: - ttr - Top net long-wave (thermal) radiation 180: - ewss - Time-integrated eastward turbulent surface stress 181: - nsss - Time-integrated northward turbulent surface stress 182: - e - Evaporation 183: - stl3 - Soil temperature level 3 184: - swl3 - Soil wetness level 3 185: - ccc - Convective cloud cover 186: - lcc - Low cloud cover 187: - mcc - Medium cloud cover 188: - hcc - High cloud cover 189: - sund - Sunshine duration 190: - ewov - East-West component of sub-gridscale orographic variance 191: - nsov - North-South component of sub-gridscale orographic variance 192: - nwov - North-West/South-East component of sub-gridscale orographic variance 193: - neov - North-East/South-West component of sub-gridscale orographic variance 194: - btmp - Brightness temperature 195: - lgws - Eastward gravity wave surface stress 196: - mgws - Northward gravity wave surface stress 197: - gwd - Gravity wave dissipation 198: - src - Skin reservoir content 199: - veg - Vegetation fraction 200: - vso - Variance of sub-gridscale orography 201: - mx2t - Maximum temperature at 2 metres since previous post-processing 202: - mn2t - Minimum temperature at 2 metres since previous post-processing 203: - o3 - Ozone mass mixing ratio 204: - paw - Precipitation analysis weights 205: - ro - Runoff 206: - tco3 - Total column ozone 207: - 10si - 10 metre wind speed 208: - tsrc - Top net short-wave (solar) radiation, clear sky 209: - ttrc - Top net long-wave (thermal) radiation, clear sky - ttru 210: - ssrc - Surface net short-wave (solar) radiation, clear sky 211: - strc - Surface net long-wave (thermal) radiation, clear sky 212: - tisr - TOA incident short-wave (solar) radiation 213: - vimd - Vertically integrated moisture divergence 214: - dhr - Diabatic heating by radiation 215: - dhvd - Diabatic heating by vertical diffusion 216: - dhcc - Diabatic heating by cumulus convection 217: - dhlc - Diabatic heating large-scale condensation 218: - vdzw - Vertical diffusion of zonal wind 219: - vdmw - Vertical diffusion of meridional wind 220: - ewgd - East-West gravity wave drag tendency 221: - nsgd - North-South gravity wave drag tendency 222: - ctzw - Convective tendency of zonal wind 223: - ctmw - Convective tendency of meridional wind 224: - vdh - Vertical diffusion of humidity 225: - htcc - Humidity tendency by cumulus convection 226: - htlc - Humidity tendency by large-scale condensation 227: - crnh - Tendency due to removal of negative humidity 228: - tp - Total precipitation 229: - iews - Instantaneous eastward turbulent surface stress 230: - inss - Instantaneous northward turbulent surface stress 231: - ishf - Instantaneous surface sensible heat net flux 232: - ie - Instantaneous moisture flux 233: - asq - Apparent surface humidity 234: - lsrh - Logarithm of surface roughness length for heat (climatological) 235: - skt - Skin temperature 236: - stl4 - Soil temperature level 4 237: - swl4 - Soil wetness level 4 238: - tsn - Temperature of snow layer 239: - csf - Convective snowfall 240: - lsf - Large-scale snowfall 241: - acf - Accumulated cloud fraction tendency 242: - alw - Accumulated liquid water tendency 243: - fal - Forecast albedo 244: - fsr - Forecast surface roughness 245: - flsr - Forecast logarithm of surface roughness for heat 246: - clwc - Specific cloud liquid water content 247: - ciwc - Specific cloud ice water content 248: - cc - Fraction of cloud cover 249: - aiw - Accumulated ice water tendency 250: - ice - Ice age 251: - atte - Adiabatic tendency of temperature 252: - athe - Adiabatic tendency of humidity 253: - atze - Adiabatic tendency of zonal wind 254: - atmw - Adiabatic tendency of meridional wind 255: - _param_000255 - Indicates a missing value 928: - thk - thicknes 956: - thka - thicknes anomaly 999: - tc - tropical cyclone 3003: - ptend - Pressure tendency 3005: - icaht - ICAO Standard Atmosphere reference height 3008: - h - Geometrical height above ground 3009: - hstdv - Standard deviation of height 3012: - vptmp - Virtual potential temperature 3014: - papt - Pseudo-adiabatic potential temperature 3015: - tmax - Maximum temperature 3016: - tmin - Minimum temperature 3017: - dpt - Dew point temperature 3018: - depr - Dew point depression (or deficit) 3019: - lapr - Lapse rate 3020: - vis - Visibility 3021: - rdsp1 - Radar spectra (1) 3022: - rdsp2 - Radar spectra (2) 3023: - rdsp3 - Radar spectra (3) 3024: - pli - Parcel lifted index (to 500 hPa) 3025: - ta - Temperature anomaly 3026: - presa - Pressure anomaly 3027: - gpa - Geopotential height anomaly 3028: - wvsp1 - Wave spectra (1) 3029: - wvsp2 - Wave spectra (2) 3030: - wvsp3 - Wave spectra (3) 3031: - wdir - Wind direction 3037: - mntsf - Montgomery stream Function 3038: - sgcvv - Sigma coordinate vertical velocity 3041: - absv - Absolute vorticity 3042: - absd - Absolute divergence 3045: - vucsh - Vertical u-component shear 3046: - vvcsh - Vertical v-component shear 3047: - dirc - Direction of current 3048: - spc - Speed of current 3049: - ucurr - U-component of current 3050: - vcurr - V-component of current 3053: - mixr - Humidity mixing ratio 3054: - pwat - Precipitable water 3055: - vp - Vapour pressure 3056: - satd - Saturation deficit 3059: - prate - Precipitation rate 3060: - tstm - Thunderstorm probability 3062: - lsp - Large-scale precipitation 3063: - acpcp - Convective precipitation (water) 3064: - srweq - Snow fall rate water equivalent 3066: - sde - Snow depth 3067: - mld - Mixed layer depth 3068: - tthdp - Transient thermocline depth 3069: - mthd - Main thermocline depth 3070: - mtha - Main thermocline anomaly 3072: - ccc - Convective cloud cover 3073: - lcc - Low cloud cover 3074: - mcc - Medium cloud cover 3075: - hcc - High cloud cover 3077: - bli - Best lifted index (to 500 hPa) 3079: - lssf - Large scale snow 3080: - wtmp - Water temperature 3082: - dslm - Deviation of sea-level from mean 3086: - ssw - Soil moisture content 3088: - s - Salinity 3089: - den - Density 3091: - icec - Ice cover (1=ice, 0=no ice) 3092: - icetk - Ice thickness 3093: - diced - Direction of ice drift 3094: - siced - Speed of ice drift 3095: - uice - U-component of ice drift 3096: - vice - V-component of ice drift 3097: - iceg - Ice growth rate 3098: - iced - Ice divergence 3099: - snom - Snowmelt 3100: - swh - Significant height of combined wind waves and swell 3101: - mdww - Mean direction of wind waves 3102: - shww - Significant height of wind waves 3103: - mpww - Mean period of wind waves 3104: - swdir - Direction of swell waves 3105: - swell - Significant height of swell waves 3106: - swper - Mean period of swell waves 3107: - mdps - Primary wave direction 3108: - mpps - Primary wave mean period 3109: - dirsw - Secondary wave direction 3110: - swp - Secondary wave mean period 3111: - nswrs - Net short-wave radiation flux (surface) 3112: - nlwrs - Net long-wave radiation flux (surface) 3113: - nswrt - Net short-wave radiation flux(atmosph.top) 3114: - nlwrt - Net long-wave radiation flux(atmosph.top) 3115: - lwavr - Long wave radiation flux 3116: - swavr - Short wave radiation flux 3117: - grad - Global radiation flux 3119: - lwrad - Radiance (with respect to wave number) 3120: - swrad - Radiance (with respect to wave length) 3121: - lhf - Latent heat flux 3122: - shf - Sensible heat flux 3123: - bld - Boundary layer dissipation 3124: - uflx - Momentum flux, u-component 3125: - vflx - Momentum flux, v-component 3126: - wmixe - Wind mixing energy 3127: - imgd - Image data 129001: - strfgrd - Stream function gradient 129002: - vpotgrd - Velocity potential gradient 129003: - ptgrd - Potential temperature gradient 129004: - eqptgrd - Equivalent potential temperature gradient 129005: - septgrd - Saturated equivalent potential temperature gradient 129011: - udvwgrd - U component of divergent wind gradient 129012: - vdvwgrd - V component of divergent wind gradient 129013: - urtwgrd - U component of rotational wind gradient 129014: - vrtwgrd - V component of rotational wind gradient 129021: - uctpgrd - Unbalanced component of temperature gradient 129022: - uclngrd - Unbalanced component of logarithm of surface pressure gradient 129023: - ucdvgrd - Unbalanced component of divergence gradient 129024: - _param_129024 - Reserved for future unbalanced components 129025: - _param_129025 - Reserved for future unbalanced components 129026: - clgrd - Lake cover gradient 129027: - cvlgrd - Low vegetation cover gradient 129028: - cvhgrd - High vegetation cover gradient 129029: - tvlgrd - Type of low vegetation gradient 129030: - tvhgrd - Type of high vegetation gradient 129031: - sicgrd - Sea-ice cover gradient 129032: - asngrd - Snow albedo gradient 129033: - rsngrd - Snow density gradient 129034: - sstkgrd - Sea surface temperature gradient 129035: - istl1grd - Ice surface temperature layer 1 gradient 129036: - istl2grd - Ice surface temperature layer 2 gradient 129037: - istl3grd - Ice surface temperature layer 3 gradient 129038: - istl4grd - Ice surface temperature layer 4 gradient 129039: - swvl1grd - Volumetric soil water layer 1 gradient 129040: - swvl2grd - Volumetric soil water layer 2 gradient 129041: - swvl3grd - Volumetric soil water layer 3 gradient 129042: - swvl4grd - Volumetric soil water layer 4 gradient 129043: - sltgrd - Soil type gradient 129044: - esgrd - Snow evaporation gradient 129045: - smltgrd - Snowmelt gradient 129046: - sdurgrd - Solar duration gradient 129047: - dsrpgrd - Direct solar radiation gradient 129048: - magssgrd - Magnitude of turbulent surface stress gradient 129049: - 10fggrd - 10 metre wind gust gradient 129050: - lspfgrd - Large-scale precipitation fraction gradient 129051: - mx2t24grd - Maximum 2 metre temperature gradient 129052: - mn2t24grd - Minimum 2 metre temperature gradient 129053: - montgrd - Montgomery potential gradient 129054: - presgrd - Pressure gradient 129055: - mean2t24grd - Mean 2 metre temperature in the last 24 hours gradient 129056: - mn2d24grd - Mean 2 metre dewpoint temperature in the last 24 hours gradient 129057: - uvbgrd - Downward UV radiation at the surface gradient 129058: - pargrd - Photosynthetically active radiation at the surface gradient 129059: - capegrd - Convective available potential energy gradient 129060: - pvgrd - Potential vorticity gradient 129061: - tpogrd - Total precipitation from observations gradient 129062: - obctgrd - Observation count gradient 129063: - _param_129063 - Start time for skin temperature difference 129064: - _param_129064 - Finish time for skin temperature difference 129065: - _param_129065 - Skin temperature difference 129066: - _param_129066 - Leaf area index, low vegetation 129067: - _param_129067 - Leaf area index, high vegetation 129070: - _param_129070 - Biome cover, low vegetation 129071: - _param_129071 - Biome cover, high vegetation 129078: - _param_129078 - Total column liquid water 129079: - _param_129079 - Total column ice water 129080: - _param_129080 - Experimental product 129081: - _param_129081 - Experimental product 129082: - _param_129082 - Experimental product 129083: - _param_129083 - Experimental product 129084: - _param_129084 - Experimental product 129085: - _param_129085 - Experimental product 129086: - _param_129086 - Experimental product 129087: - _param_129087 - Experimental product 129088: - _param_129088 - Experimental product 129089: - _param_129089 - Experimental product 129090: - _param_129090 - Experimental product 129091: - _param_129091 - Experimental product 129092: - _param_129092 - Experimental product 129093: - _param_129093 - Experimental product 129094: - _param_129094 - Experimental product 129095: - _param_129095 - Experimental product 129096: - _param_129096 - Experimental product 129097: - _param_129097 - Experimental product 129098: - _param_129098 - Experimental product 129099: - _param_129099 - Experimental product 129100: - _param_129100 - Experimental product 129101: - _param_129101 - Experimental product 129102: - _param_129102 - Experimental product 129103: - _param_129103 - Experimental product 129104: - _param_129104 - Experimental product 129105: - _param_129105 - Experimental product 129106: - _param_129106 - Experimental product 129107: - _param_129107 - Experimental product 129108: - _param_129108 - Experimental product 129109: - _param_129109 - Experimental product 129110: - _param_129110 - Experimental product 129111: - _param_129111 - Experimental product 129112: - _param_129112 - Experimental product 129113: - _param_129113 - Experimental product 129114: - _param_129114 - Experimental product 129115: - _param_129115 - Experimental product 129116: - _param_129116 - Experimental product 129117: - _param_129117 - Experimental product 129118: - _param_129118 - Experimental product 129119: - _param_129119 - Experimental product 129120: - _param_129120 - Experimental product 129121: - mx2t6grd - Maximum temperature at 2 metres gradient 129122: - mn2t6grd - Minimum temperature at 2 metres gradient 129123: - 10fg6grd - 10 metre wind gust in the last 6 hours gradient 129125: - _param_129125 - Vertically integrated total energy 129126: - _param_129126 - Generic parameter for sensitive area prediction 129127: - atgrd - Atmospheric tide gradient 129128: - bvgrd - Budget values gradient 129129: - zgrd - Geopotential gradient 129130: - tgrd - Temperature gradient 129131: - ugrd - U component of wind gradient 129132: - vgrd - V component of wind gradient 129133: - qgrd - Specific humidity gradient 129134: - spgrd - Surface pressure gradient 129135: - wgrd - vertical velocity (pressure) gradient 129136: - tcwgrd - Total column water gradient 129137: - tcwvgrd - Total column water vapour gradient 129138: - vogrd - Vorticity (relative) gradient 129139: - stl1grd - Soil temperature level 1 gradient 129140: - swl1grd - Soil wetness level 1 gradient 129141: - sdgrd - Snow depth gradient 129142: - lspgrd - Stratiform precipitation (Large-scale precipitation) gradient 129143: - cpgrd - Convective precipitation gradient 129144: - sfgrd - Snowfall (convective + stratiform) gradient 129145: - bldgrd - Boundary layer dissipation gradient 129146: - sshfgrd - Surface sensible heat flux gradient 129147: - slhfgrd - Surface latent heat flux gradient 129148: - chnkgrd - Charnock gradient 129149: - snrgrd - Surface net radiation gradient 129150: - tnrgrd - Top net radiation gradient 129151: - mslgrd - Mean sea level pressure gradient 129152: - lnspgrd - Logarithm of surface pressure gradient 129153: - swhrgrd - Short-wave heating rate gradient 129154: - lwhrgrd - Long-wave heating rate gradient 129155: - dgrd - Divergence gradient 129156: - ghgrd - Height gradient 129157: - rgrd - Relative humidity gradient 129158: - tspgrd - Tendency of surface pressure gradient 129159: - blhgrd - Boundary layer height gradient 129160: - sdorgrd - Standard deviation of orography gradient 129161: - isorgrd - Anisotropy of sub-gridscale orography gradient 129162: - anorgrd - Angle of sub-gridscale orography gradient 129163: - slorgrd - Slope of sub-gridscale orography gradient 129164: - tccgrd - Total cloud cover gradient 129165: - 10ugrd - 10 metre U wind component gradient 129166: - 10vgrd - 10 metre V wind component gradient 129167: - 2tgrd - 2 metre temperature gradient 129168: - 2dgrd - 2 metre dewpoint temperature gradient 129169: - ssrdgrd - Surface solar radiation downwards gradient 129170: - stl2grd - Soil temperature level 2 gradient 129171: - swl2grd - Soil wetness level 2 gradient 129172: - lsmgrd - Land-sea mask gradient 129173: - srgrd - Surface roughness gradient 129174: - algrd - Albedo gradient 129175: - strdgrd - Surface thermal radiation downwards gradient 129176: - ssrgrd - Surface net solar radiation gradient 129177: - strgrd - Surface net thermal radiation gradient 129178: - tsrgrd - Top net solar radiation gradient 129179: - ttrgrd - Top net thermal radiation gradient 129180: - ewssgrd - East-West surface stress gradient 129181: - nsssgrd - North-South surface stress gradient 129182: - egrd - Evaporation gradient 129183: - stl3grd - Soil temperature level 3 gradient 129184: - swl3grd - Soil wetness level 3 gradient 129185: - cccgrd - Convective cloud cover gradient 129186: - lccgrd - Low cloud cover gradient 129187: - mccgrd - Medium cloud cover gradient 129188: - hccgrd - High cloud cover gradient 129189: - sundgrd - Sunshine duration gradient 129190: - ewovgrd - East-West component of sub-gridscale orographic variance gradient 129191: - nsovgrd - North-South component of sub-gridscale orographic variance gradient 129192: - nwovgrd - North-West/South-East component of sub-gridscale orographic variance gradient 129193: - neovgrd - North-East/South-West component of sub-gridscale orographic variance gradient 129194: - btmpgrd - Brightness temperature gradient 129195: - lgwsgrd - Longitudinal component of gravity wave stress gradient 129196: - mgwsgrd - Meridional component of gravity wave stress gradient 129197: - gwdgrd - Gravity wave dissipation gradient 129198: - srcgrd - Skin reservoir content gradient 129199: - veggrd - Vegetation fraction gradient 129200: - vsogrd - Variance of sub-gridscale orography gradient 129201: - mx2tgrd - Maximum temperature at 2 metres since previous post-processing gradient 129202: - mn2tgrd - Minimum temperature at 2 metres since previous post-processing gradient 129203: - o3grd - Ozone mass mixing ratio gradient 129204: - pawgrd - Precipitation analysis weights gradient 129205: - rogrd - Runoff gradient 129206: - tco3grd - Total column ozone gradient 129207: - 10sigrd - 10 metre wind speed gradient 129208: - tsrcgrd - Top net solar radiation, clear sky gradient 129209: - ttrcgrd - Top net thermal radiation, clear sky gradient 129210: - ssrcgrd - Surface net solar radiation, clear sky gradient 129211: - strcgrd - Surface net thermal radiation, clear sky gradient 129212: - tisrgrd - TOA incident solar radiation gradient 129214: - dhrgrd - Diabatic heating by radiation gradient 129215: - dhvdgrd - Diabatic heating by vertical diffusion gradient 129216: - dhccgrd - Diabatic heating by cumulus convection gradient 129217: - dhlcgrd - Diabatic heating large-scale condensation gradient 129218: - vdzwgrd - Vertical diffusion of zonal wind gradient 129219: - vdmwgrd - Vertical diffusion of meridional wind gradient 129220: - ewgdgrd - East-West gravity wave drag tendency gradient 129221: - nsgdgrd - North-South gravity wave drag tendency gradient 129222: - ctzwgrd - Convective tendency of zonal wind gradient 129223: - ctmwgrd - Convective tendency of meridional wind gradient 129224: - vdhgrd - Vertical diffusion of humidity gradient 129225: - htccgrd - Humidity tendency by cumulus convection gradient 129226: - htlcgrd - Humidity tendency by large-scale condensation gradient 129227: - crnhgrd - Change from removal of negative humidity gradient 129228: - tpgrd - Total precipitation gradient 129229: - iewsgrd - Instantaneous X surface stress gradient 129230: - inssgrd - Instantaneous Y surface stress gradient 129231: - ishfgrd - Instantaneous surface heat flux gradient 129232: - iegrd - Instantaneous moisture flux gradient 129233: - asqgrd - Apparent surface humidity gradient 129234: - lsrhgrd - Logarithm of surface roughness length for heat gradient 129235: - sktgrd - Skin temperature gradient 129236: - stl4grd - Soil temperature level 4 gradient 129237: - swl4grd - Soil wetness level 4 gradient 129238: - tsngrd - Temperature of snow layer gradient 129239: - csfgrd - Convective snowfall gradient 129240: - lsfgrd - Large scale snowfall gradient 129241: - acfgrd - Accumulated cloud fraction tendency gradient 129242: - alwgrd - Accumulated liquid water tendency gradient 129243: - falgrd - Forecast albedo gradient 129244: - fsrgrd - Forecast surface roughness gradient 129245: - flsrgrd - Forecast logarithm of surface roughness for heat gradient 129246: - clwcgrd - Specific cloud liquid water content gradient 129247: - ciwcgrd - Specific cloud ice water content gradient 129248: - ccgrd - Cloud cover gradient 129249: - aiwgrd - Accumulated ice water tendency gradient 129250: - icegrd - Ice age gradient 129251: - attegrd - Adiabatic tendency of temperature gradient 129252: - athegrd - Adiabatic tendency of humidity gradient 129253: - atzegrd - Adiabatic tendency of zonal wind gradient 129254: - atmwgrd - Adiabatic tendency of meridional wind gradient 129255: - _param_129255 - Indicates a missing value 130208: - tsru - Top solar radiation upward 130209: - ttru - Top thermal radiation upward 130210: - tsuc - Top solar radiation upward, clear sky 130211: - ttuc - Top thermal radiation upward, clear sky 130212: - clw - Cloud liquid water 130213: - cf - Cloud fraction 130214: - dhr - Diabatic heating by radiation 130215: - dhvd - Diabatic heating by vertical diffusion 130216: - dhcc - Diabatic heating by cumulus convection 130217: - dhlc - Diabatic heating by large-scale condensation 130218: - vdzw - Vertical diffusion of zonal wind 130219: - vdmw - Vertical diffusion of meridional wind 130220: - ewgd - East-West gravity wave drag 130221: - nsgd - North-South gravity wave drag 130224: - vdh - Vertical diffusion of humidity 130225: - htcc - Humidity tendency by cumulus convection 130226: - htlc - Humidity tendency by large-scale condensation 130228: - att - Adiabatic tendency of temperature 130229: - ath - Adiabatic tendency of humidity 130230: - atzw - Adiabatic tendency of zonal wind 130231: - atmwax - Adiabatic tendency of meridional wind 130232: - mvv - Mean vertical velocity 131001: - 2tag2 - 2m temperature anomaly of at least +2K 131002: - 2tag1 - 2m temperature anomaly of at least +1K 131003: - 2tag0 - 2m temperature anomaly of at least 0K 131004: - 2talm1 - 2m temperature anomaly of at most -1K 131005: - 2talm2 - 2m temperature anomaly of at most -2K 131006: - tpag20 - Total precipitation anomaly of at least 20 mm 131007: - tpag10 - Total precipitation anomaly of at least 10 mm 131008: - tpag0 - Total precipitation anomaly of at least 0 mm 131009: - stag0 - Surface temperature anomaly of at least 0K 131010: - mslag0 - Mean sea level pressure anomaly of at least 0 Pa 131015: - h0dip - Height of 0 degree isotherm probability 131016: - hslp - Height of snowfall limit probability 131017: - saip - Showalter index probability 131018: - whip - Whiting index probability 131020: - talm2 - Temperature anomaly less than -2 K - temperature anomaly of at most -2 k 131021: - tag2 - Temperature anomaly of at least +2 K - temperature anomaly of at least 2 k 131022: - talm8 - Temperature anomaly less than -8 K - temperature anomaly of at most -8 k 131023: - talm4 - Temperature anomaly less than -4 K - temperature anomaly of at most -4 k 131024: - tag4 - Temperature anomaly greater than +4 K - temperature anomaly greater than 4 k - temperature anomaly of at least 4 k 131025: - tag8 - Temperature anomaly greater than +8 K - temperature anomaly greater than 8 k - temperature anomaly of at least 8 k 131049: - 10gp - 10 metre wind gust probability 131059: - capep - Convective available potential energy probability 131060: - tpg1 - Total precipitation of at least 1 mm 131061: - tpg5 - Total precipitation of at least 5 mm 131062: - tpg10 - Total precipitation of at least 10 mm 131063: - tpg20 - Total precipitation of at least 20 mm 131064: - tpl01 - Total precipitation less than 0.1 mm 131065: - tprl1 - Total precipitation rate less than 1 mm/day 131066: - tprg3 - Total precipitation rate of at least 3 mm/day 131067: - tprg5 - Total precipitation rate of at least 5 mm/day 131068: - 10spg10 - 10 metre Wind speed of at least 10 m/s 131069: - 10spg15 - 10 metre Wind speed of at least 15 m/s 131070: - 10fgg15 - 10 metre wind gust of at least 15 m/s 131071: - 10fgg20 - 10 metre wind gust of at least 20 m/s 131072: - 10fgg25 - 10 metre wind gust of at least 25 m/s 131073: - 2tl273 - 2 metre temperature less than 273.15 K 131074: - swhg2 - Significant wave height of at least 2 m 131075: - swhg4 - Significant wave height of at least 4 m 131076: - swhg6 - Significant wave height of at least 6 m 131077: - swhg8 - Significant wave height of at least 8 m 131078: - mwpg8 - Mean wave period of at least 8 s 131079: - mwpg10 - Mean wave period of at least 10 s 131080: - mwpg12 - Mean wave period of at least 12 s 131081: - mwpg15 - Mean wave period of at least 15 s 131082: - tpg40 - Total precipitation of at least 40 mm 131083: - tpg60 - Total precipitation of at least 60 mm 131084: - tpg80 - Total precipitation of at least 80 mm 131085: - tpg100 - Total precipitation of at least 100 mm 131086: - tpg150 - Total precipitation of at least 150 mm 131087: - tpg200 - Total precipitation of at least 200 mm 131088: - tpg300 - Total precipitation of at least 300 mm 131089: - pts - Probability of a tropical storm 131090: - ph - Probability of a hurricane 131091: - ptd - Probability of a tropical depression 131092: - cpts - Climatological probability of a tropical storm 131093: - cph - Climatological probability of a hurricane 131094: - cptd - Climatological probability of a tropical depression 131095: - pats - Probability anomaly of a tropical storm 131096: - pah - Probability anomaly of a hurricane 131097: - patd - Probability anomaly of a tropical depression 131098: - tpg25 - Total precipitation of at least 25 mm 131099: - tpg50 - Total precipitation of at least 50 mm 131100: - 10fgg10 - 10 metre wind gust of at least 10 m/s 131129: - zp - Geopotential probability 131130: - tap - Temperature anomaly probability 131139: - stl1p - Soil temperature level 1 probability 131144: - sfp - Snowfall (convective + stratiform) probability 131151: - mslpp - Mean sea level pressure probability 131164: - tccp - Total cloud cover probability 131165: - 10sp - 10 metre speed probability 131167: - 2tp - 2 metre temperature probability 131201: - mx2tp - Maximum 2 metre temperature probability 131202: - mn2tp - Minimum 2 metre temperature probability 131228: - tpp - Total precipitation probability 131229: - swhp - Significant wave height probability 131232: - mwpp - Mean wave period probability 131255: - _param_131255 - Indicates a missing value 131256: - 10cogug25 - 10 metre convective gust of at least 25 m/s 132044: - capesi - Convective available potential energy shear index 132045: - wvfi - Water vapour flux index 132049: - 10fgi - 10 metre wind gust index - 10gi 132059: - capei - Convective available potential energy index 132144: - sfi - Snowfall index 132165: - 10wsi - 10 metre speed index 132167: - 2ti - 2 metre temperature index 132201: - mx2ti - Maximum temperature at 2 metres index 132202: - mn2ti - Minimum temperature at 2 metres index 132216: - maxswhi - Maximum of significant wave height index 132228: - tpi - Total precipitation index 133001: - 2tplm10 - 2m temperature probability less than -10 C 133002: - 2tplm5 - 2m temperature probability less than -5 C 133003: - 2tpl0 - 2m temperature probability less than 0 C 133004: - 2tpl5 - 2m temperature probability less than 5 C 133005: - 2tpl10 - 2m temperature probability less than 10 C 133006: - 2tpg25 - 2m temperature probability greater than 25 C 133007: - 2tpg30 - 2m temperature probability greater than 30 C 133008: - 2tpg35 - 2m temperature probability greater than 35 C 133009: - 2tpg40 - 2m temperature probability greater than 40 C 133010: - 2tpg45 - 2m temperature probability greater than 45 C 133011: - mn2tplm10 - Minimum 2 metre temperature probability less than -10 C 133012: - mn2tplm5 - Minimum 2 metre temperature probability less than -5 C 133013: - mn2tpl0 - Minimum 2 metre temperature probability less than 0 C 133014: - mn2tpl5 - Minimum 2 metre temperature probability less than 5 C 133015: - mn2tpl10 - Minimum 2 metre temperature probability less than 10 C 133016: - mx2tpg25 - Maximum 2 metre temperature probability greater than 25 C 133017: - mx2tpg30 - Maximum 2 metre temperature probability greater than 30 C 133018: - mx2tpg35 - Maximum 2 metre temperature probability greater than 35 C 133019: - mx2tpg40 - Maximum 2 metre temperature probability greater than 40 C 133020: - mx2tpg45 - Maximum 2 metre temperature probability greater than 45 C 133021: - 10spg10 - 10 metre wind speed probability of at least 10 m/s 133022: - 10spg15 - 10 metre wind speed probability of at least 15 m/s 133023: - 10spg20 - 10 metre wind speed probability of at least 20 m/s 133024: - 10spg35 - 10 metre wind speed probability of at least 35 m/s 133025: - 10spg50 - 10 metre wind speed probability of at least 50 m/s 133026: - 10gpg20 - 10 metre wind gust probability of at least 20 m/s 133027: - 10gpg35 - 10 metre wind gust probability of at least 35 m/s 133028: - 10gpg50 - 10 metre wind gust probability of at least 50 m/s 133029: - 10gpg75 - 10 metre wind gust probability of at least 75 m/s 133030: - 10gpg100 - 10 metre wind gust probability of at least 100 m/s 133031: - tppg1 - Total precipitation probability of at least 1 mm 133032: - tppg5 - Total precipitation probability of at least 5 mm 133033: - tppg10 - Total precipitation probability of at least 10 mm 133034: - tppg20 - Total precipitation probability of at least 20 mm 133035: - tppg40 - Total precipitation probability of at least 40 mm 133036: - tppg60 - Total precipitation probability of at least 60 mm 133037: - tppg80 - Total precipitation probability of at least 80 mm 133038: - tppg100 - Total precipitation probability of at least 100 mm 133039: - tppg150 - Total precipitation probability of at least 150 mm 133040: - tppg200 - Total precipitation probability of at least 200 mm 133041: - tppg300 - Total precipitation probability of at least 300 mm 133042: - sfpg1 - Snowfall probability of at least 1 mm 133043: - sfpg5 - Snowfall probability of at least 5 mm 133044: - sfpg10 - Snowfall probability of at least 10 mm 133045: - sfpg20 - Snowfall probability of at least 20 mm 133046: - sfpg40 - Snowfall probability of at least 40 mm 133047: - sfpg60 - Snowfall probability of at least 60 mm 133048: - sfpg80 - Snowfall probability of at least 80 mm 133049: - sfpg100 - Snowfall probability of at least 100 mm 133050: - sfpg150 - Snowfall probability of at least 150 mm 133051: - sfpg200 - Snowfall probability of at least 200 mm 133052: - sfpg300 - Snowfall probability of at least 300 mm 133053: - tccpg10 - Total Cloud Cover probability greater than 10% 133054: - tccpg20 - Total Cloud Cover probability greater than 20% 133055: - tccpg30 - Total Cloud Cover probability greater than 30% 133056: - tccpg40 - Total Cloud Cover probability greater than 40% 133057: - tccpg50 - Total Cloud Cover probability greater than 50% 133058: - tccpg60 - Total Cloud Cover probability greater than 60% 133059: - tccpg70 - Total Cloud Cover probability greater than 70% 133060: - tccpg80 - Total Cloud Cover probability greater than 80% 133061: - tccpg90 - Total Cloud Cover probability greater than 90% 133062: - tccpg99 - Total Cloud Cover probability greater than 99% 133063: - hccpg10 - High Cloud Cover probability greater than 10% 133064: - hccpg20 - High Cloud Cover probability greater than 20% 133065: - hccpg30 - High Cloud Cover probability greater than 30% 133066: - hccpg40 - High Cloud Cover probability greater than 40% 133067: - hccpg50 - High Cloud Cover probability greater than 50% 133068: - hccpg60 - High Cloud Cover probability greater than 60% 133069: - hccpg70 - High Cloud Cover probability greater than 70% 133070: - hccpg80 - High Cloud Cover probability greater than 80% 133071: - hccpg90 - High Cloud Cover probability greater than 90% 133072: - hccpg99 - High Cloud Cover probability greater than 99% 133073: - mccpg10 - Medium Cloud Cover probability greater than 10% 133074: - mccpg20 - Medium Cloud Cover probability greater than 20% 133075: - mccpg30 - Medium Cloud Cover probability greater than 30% 133076: - mccpg40 - Medium Cloud Cover probability greater than 40% 133077: - mccpg50 - Medium Cloud Cover probability greater than 50% 133078: - mccpg60 - Medium Cloud Cover probability greater than 60% 133079: - mccpg70 - Medium Cloud Cover probability greater than 70% 133080: - mccpg80 - Medium Cloud Cover probability greater than 80% 133081: - mccpg90 - Medium Cloud Cover probability greater than 90% 133082: - mccpg99 - Medium Cloud Cover probability greater than 99% 133083: - lccpg10 - Low Cloud Cover probability greater than 10% 133084: - lccpg20 - Low Cloud Cover probability greater than 20% 133085: - lccpg30 - Low Cloud Cover probability greater than 30% 133086: - lccpg40 - Low Cloud Cover probability greater than 40% 133087: - lccpg50 - Low Cloud Cover probability greater than 50% 133088: - lccpg60 - Low Cloud Cover probability greater than 60% 133089: - lccpg70 - Low Cloud Cover probability greater than 70% 133090: - lccpg80 - Low Cloud Cover probability greater than 80% 133091: - lccpg90 - Low Cloud Cover probability greater than 90% 133092: - lccpg99 - Low Cloud Cover probability greater than 99% 133093: - ptsa_gt_1stdev - Probability of temperature standardized anomaly greater than 1 standard deviation 133094: - ptsa_gt_1p5stdev - Probability of temperature standardized anomaly greater than 1.5 standard deviation 133095: - ptsa_gt_2stdev - Probability of temperature standardized anomaly greater than 2 standard deviation 133096: - ptsa_lt_1stdev - Probability of temperature standardized anomaly less than -1 standard deviation 133097: - ptsa_lt_1p5stdev - Probability of temperature standardized anomaly less than -1.5 standard deviation 133098: - ptsa_lt_2stdev - Probability of temperature standardized anomaly less than -2 standard deviation 140080: - wx1 - Wave experimental parameter 1 140081: - wx2 - Wave experimental parameter 2 140082: - wx3 - Wave experimental parameter 3 140083: - wx4 - Wave experimental parameter 4 140084: - wx5 - Wave experimental parameter 5 140098: - weta - Wave induced mean sea level correction 140099: - wraf - Ratio of wave angular and frequency width 140100: - wnslc - Number of events in freak waves statistics 140101: - utaua - U-component of atmospheric surface momentum flux 140102: - vtaua - V-component of atmospheric surface momentum flux 140103: - utauo - U-component of surface momentum flux into ocean 140104: - vtauo - V-component of surface momentum flux into ocean 140105: - wphio - Wave turbulent energy flux into ocean 140106: - wdw1 - Wave directional width of first swell partition 140107: - wfw1 - Wave frequency width of first swell partition 140108: - wdw2 - Wave directional width of second swell partition 140109: - wfw2 - Wave frequency width of second swell partition 140110: - wdw3 - Wave directional width of third swell partition 140111: - wfw3 - Wave frequency width of third swell partition 140112: - wefxm - Wave energy flux magnitude 140113: - wefxd - Wave energy flux mean direction 140114: - h1012 - Significant wave height of all waves with periods within the inclusive range from 10 to 12 seconds 140115: - h1214 - Significant wave height of all waves with periods within the inclusive range from 12 to 14 seconds 140116: - h1417 - Significant wave height of all waves with periods within the inclusive range from 14 to 17 seconds 140117: - h1721 - Significant wave height of all waves with periods within the inclusive range from 17 to 21 seconds 140118: - h2125 - Significant wave height of all waves with periods within the inclusive range from 21 to 25 seconds 140119: - h2530 - Significant wave height of all waves with periods within the inclusive range from 25 to 30 seconds 140120: - sh10 - Significant wave height of all waves with period larger than 10s 140121: - swh1 - Significant wave height of first swell partition 140122: - mwd1 - Mean wave direction of first swell partition 140123: - mwp1 - Mean wave period of first swell partition 140124: - swh2 - Significant wave height of second swell partition 140125: - mwd2 - Mean wave direction of second swell partition 140126: - mwp2 - Mean wave period of second swell partition 140127: - swh3 - Significant wave height of third swell partition 140128: - mwd3 - Mean wave direction of third swell partition 140129: - mwp3 - Mean wave period of third swell partition 140131: - tdcmax - Time domain maximum individual crest height 140132: - tdhmax - Time domain maximum individual wave height 140133: - stcmax - Space time maximum individual crest height 140134: - sthmax - Space time maximum individual wave height 140135: - pp1dw - Peak wave period of wind waves 140136: - pp1ds - Peak wave period of total swell 140137: - pp1d1 - Peak wave period of first swell partition 140138: - pp1d2 - Peak wave period of second swell partition 140139: - pp1d3 - Peak wave period of third swell partition 140140: - pwd - Peak wave direction (total) 140141: - pwdw - Peak wave direction of wind waves 140142: - pwds - Peak wave direction of total swell 140143: - pwd1 - Peak wave direction of first swell partition 140144: - pwd2 - Peak wave direction of second swell partition 140145: - pwd3 - Peak wave direction of third swell partition 140146: - wcfr - Whitecap fraction 140147: - bfi2d - Benjamin-Feir index 2D 140148: - ctc - Crest-trough correlation 140149: - xwrs - X component of the wave radiative stress to sea ice 140150: - ywrs - Y component of the wave radiative stress to sea ice 140200: - maxswh - Maximum of significant wave height 140207: - wss - Wave Spectral Skewness 140208: - wstar - Free convective velocity over the oceans 140209: - rhoao - Air density over the oceans 140210: - mswsi - Mean square wave strain in sea ice 140211: - phiaw - Normalized energy flux into waves 140212: - phioc - Normalized energy flux into ocean 140213: - tla - Turbulent Langmuir number 140214: - tauoc - Normalized stress into ocean 140215: - ust - U-component surface stokes drift 140216: - vst - V-component surface stokes drift 140217: - tmax - Period corresponding to maximum individual wave height 140218: - hmax - Envelop-maximum individual wave height 140219: - wmb - Model bathymetry 140220: - mp1 - Mean wave period based on first moment 140221: - mp2 - Mean zero-crossing wave period 140222: - wdw - Wave spectral directional width 140223: - p1ww - Mean wave period based on first moment for wind waves 140224: - p2ww - Mean wave period based on second moment for wind waves 140225: - dwww - Wave spectral directional width for wind waves 140226: - p1ps - Mean wave period based on first moment for swell 140227: - p2ps - Mean wave period based on second moment for swell 140228: - dwps - Wave spectral directional width for swell 140229: - swh - Significant height of combined wind waves and swell 140230: - mwd - Mean wave direction 140231: - pp1d - Peak wave period 140232: - mwp - Mean wave period 140233: - cdww - Coefficient of drag with waves 140234: - shww - Significant height of wind waves 140235: - mdww - Mean direction of wind waves 140236: - mpww - Mean period of wind waves 140237: - shts - Significant height of total swell 140238: - mdts - Mean direction of total swell 140239: - mpts - Mean period of total swell 140240: - sdhs - Standard deviation wave height 140241: - mu10 - Mean of 10 metre wind speed 140242: - mdwi - Mean wind direction 140243: - sdu - Standard deviation of 10 metre wind speed 140244: - msqs - Mean square slope of waves 140245: - wind - 10 metre wind speed 140246: - awh - Altimeter wave height 140247: - acwh - Altimeter corrected wave height 140248: - arrc - Altimeter range relative correction 140249: - dwi - 10 metre wind direction 140250: - 2dsp - 2D wave spectra (multiple) 140251: - 2dfd - 2D wave spectra (single) 140252: - wsk - Wave spectral kurtosis 140253: - bfi - Benjamin-Feir index 140254: - wsp - Wave spectral peakedness 140255: - _param_140255 - Indicates a missing value 141098: - avg_weta - Time-mean wave induced mean sea level correction 141099: - avg_wraf - Time-mean ratio of wave angular and frequency width 141100: - avg_wnslc - Time-mean number of events in freak waves statistics 141101: - avg_utaua - Time-mean U-component of atmospheric surface momentum flux 141102: - avg_vtaua - Time-mean V-component of atmospheric surface momentum flux 141103: - avg_utauo - Time-mean U-component of surface momentum flux into ocean 141104: - avg_vtauo - Time-mean V-component of surface momentum flux into ocean 141105: - avg_wphio - Time-mean wave turbulent energy flux into ocean 141106: - avg_wdw1 - Time-mean wave directional width of first swell partition 141107: - avg_wfw1 - Time-mean wave frequency width of first swell partition 141108: - avg_wdw2 - Time-mean wave directional width of second swell partition 141109: - avg_wfw2 - Time-mean wave frequency width of second swell partition 141110: - avg_wdw3 - Time-mean wave directional width of third swell partition 141111: - avg_wfw3 - Time-mean wave frequency width of third swell partition 141112: - avg_wefxm - Time-mean wave energy flux magnitude 141113: - avg_wefxd - Time-mean wave energy flux mean direction 141114: - avg_h1012 - Time-mean significant wave height of all waves with periods within the inclusive range from 10 to 12 seconds 141115: - avg_h1214 - Time-mean significant wave height of all waves with periods within the inclusive range from 12 to 14 seconds 141116: - avg_h1417 - Time-mean significant wave height of all waves with periods within the inclusive range from 14 to 17 seconds 141117: - avg_h1721 - Time-mean significant wave height of all waves with periods within the inclusive range from 17 to 21 seconds 141118: - avg_h2125 - Time-mean significant wave height of all waves with periods within the inclusive range from 21 to 25 seconds 141119: - avg_h2530 - Time-mean significant wave height of all waves with periods within the inclusive range from 25 to 30 seconds 141120: - avg_sh10 - Time-mean significant wave height of all waves with period larger than 10s 141121: - avg_swh1 - Time-mean significant wave height of first swell partition 141122: - avg_mwd1 - Time-mean mean wave direction of first swell partition 141123: - avg_mwp1 - Time-mean mean wave period of first swell partition 141124: - avg_swh2 - Time-mean significant wave height of second swell partition 141125: - avg_mwd2 - Time-mean mean wave direction of second swell partition 141126: - avg_mwp2 - Time-mean mean wave period of second swell partition 141127: - avg_swh3 - Time-mean significant wave height of third swell partition 141128: - avg_mwd3 - Time-mean mean wave direction of third swell partition 141129: - avg_mwp3 - Time-mean mean wave period of third swell partition 141131: - avg_tdcmax - Time-mean time domain maximum individual crest height 141132: - avg_tdhmax - Time-mean time domain maximum individual wave height 141133: - avg_stcmax - Time-mean space time maximum individual crest height 141134: - avg_sthmax - Time-mean space time maximum individual wave height 141135: - avg_pp1dw - Time-mean peak wave period of wind waves 141136: - avg_pp1ds - Time-mean peak wave period of total swell 141137: - avg_pp1d1 - Time-mean peak wave period of first swell partition 141138: - avg_pp1d2 - Time-mean peak wave period of second swell partition 141139: - avg_pp1d3 - Time-mean peak wave period of third swell partition 141140: - avg_pwd - Time-mean peak wave direction (total) 141141: - avg_pwdw - Time-mean peak wave direction of wind waves 141142: - avg_pwds - Time-mean peak wave direction of total swell 141143: - avg_pwd1 - Time-mean peak wave direction of first swell partition 141144: - avg_pwd2 - Time-mean peak wave direction of second swell partition 141145: - avg_pwd3 - Time-mean peak wave direction of third swell partition 141146: - avg_wcfr - Time-mean whitecap fraction 141147: - avg_bfi2d - Time-mean Benjamin-Feir index 2D 141148: - avg_ctc - Time-mean crest-trough correlation 141149: - avg_xwrs - Time-mean X component of the wave radiative stress to sea ice 141150: - avg_ywrs - Time-mean Y component of the wave radiative stress to sea ice 141207: - avg_wss - Time-mean wave Spectral Skewness 141208: - avg_wstar - Time-mean free convective velocity over the oceans 141209: - avg_rhoao - Time-mean air density over the oceans 141211: - avg_phiaw - Time-mean normalized energy flux into waves 141212: - avg_phioc - Time-mean normalized energy flux into ocean 141214: - avg_tauoc - Time-mean normalized stress into ocean 141215: - avg_ust - Time-mean U-component surface stokes drift 141216: - avg_vst - Time-mean V-component surface stokes drift 141217: - avg_tmax - Time-mean period corresponding to maximum individual wave height 141218: - avg_hmax - Time-mean envelop-maximum individual wave height 141220: - avg_mp1 - Time-mean mean wave period based on first moment 141221: - avg_mp2 - Time-mean mean zero-crossing wave period 141222: - avg_wdw - Time-mean wave spectral directional width 141223: - avg_p1ww - Time-mean mean wave period based on first moment for wind waves 141224: - avg_p2ww - Time-mean mean wave period based on second moment for wind waves 141225: - avg_dwww - Time-mean wave spectral directional width for wind waves 141226: - avg_p1ps - Time-mean mean wave period based on first moment for swell 141227: - avg_p2ps - Time-mean mean wave period based on second moment for swell 141228: - avg_dwps - Time-mean wave spectral directional width for swell 141229: - avg_swh - Time-mean significant height of combined wind waves and swell 141230: - avg_mwd - Time-mean mean wave direction 141231: - avg_pp1d - Time-mean peak wave period 141232: - avg_mwp - Time-mean mean wave period 141233: - avg_cdww - Time-mean coefficient of drag with waves 141234: - avg_shww - Time-mean significant height of wind waves 141235: - avg_mdww - Time-mean mean direction of wind waves 141236: - avg_mpww - Time-mean mean period of wind waves 141237: - avg_shts - Time-mean significant height of total swell 141238: - avg_mdts - Time-mean mean direction of total swell 141239: - avg_mpts - Time-mean mean period of total swell 141244: - avg_msqs - Time-mean mean square slope of waves 141245: - avg_wind - Time-mean 10 metre wind speed 141249: - avg_dwi - Time-mean 10 metre wind direction 141252: - avg_wsk - Time-mean wave spectral kurtosis 141253: - avg_bfi - Time-mean benjamin-Feir index 141254: - avg_wsp - Time-mean wave spectral peakedness 143098: - max_weta - Time-maximum wave induced mean sea level correction 143099: - max_wraf - Time-maximum ratio of wave angular and frequency width 143100: - max_wnslc - Time-maximum number of events in freak waves statistics 143101: - max_utaua - Time-maximum U-component of atmospheric surface momentum flux 143102: - max_vtaua - Time-maximum V-component of atmospheric surface momentum flux 143103: - max_utauo - Time-maximum U-component of surface momentum flux into ocean 143104: - max_vtauo - Time-maximum V-component of surface momentum flux into ocean 143105: - max_wphio - Time-maximum wave turbulent energy flux into ocean 143106: - max_wdw1 - Time-maximum wave directional width of first swell partition 143107: - max_wfw1 - Time-maximum wave frequency width of first swell partition 143108: - max_wdw2 - Time-maximum wave directional width of second swell partition 143109: - max_wfw2 - Time-maximum wave frequency width of second swell partition 143110: - max_wdw3 - Time-maximum wave directional width of third swell partition 143111: - max_wfw3 - Time-maximum wave frequency width of third swell partition 143112: - max_wefxm - Time-maximum wave energy flux magnitude 143113: - max_wefxd - Time-maximum wave energy flux mean direction 143114: - max_h1012 - Time-maximum significant wave height of all waves with periods within the inclusive range from 10 to 12 seconds 143115: - max_h1214 - Time-maximum significant wave height of all waves with periods within the inclusive range from 12 to 14 seconds 143116: - max_h1417 - Time-maximum significant wave height of all waves with periods within the inclusive range from 14 to 17 seconds 143117: - max_h1721 - Time-maximum significant wave height of all waves with periods within the inclusive range from 17 to 21 seconds 143118: - max_h2125 - Time-maximum significant wave height of all waves with periods within the inclusive range from 21 to 25 seconds 143119: - max_h2530 - Time-maximum significant wave height of all waves with periods within the inclusive range from 25 to 30 seconds 143120: - max_sh10 - Time-maximum significant wave height of all waves with period larger than 10s 143121: - max_swh1 - Time-maximum significant wave height of first swell partition 143122: - max_mwd1 - Time-maximum mean wave direction of first swell partition 143123: - max_mwp1 - Time-maximum mean wave period of first swell partition 143124: - max_swh2 - Time-maximum significant wave height of second swell partition 143125: - max_mwd2 - Time-maximum mean wave direction of second swell partition 143126: - max_mwp2 - Time-maximum mean wave period of second swell partition 143127: - max_swh3 - Time-maximum significant wave height of third swell partition 143128: - max_mwd3 - Time-maximum mean wave direction of third swell partition 143129: - max_mwp3 - Time-maximum mean wave period of third swell partition 143131: - max_tdcmax - Time-maximum time domain maximum individual crest height 143132: - max_tdhmax - Time-maximum time domain maximum individual wave height 143133: - max_stcmax - Time-maximum space time maximum individual crest height 143134: - max_sthmax - Time-maximum space time maximum individual wave height 143135: - max_pp1dw - Time-maximum peak wave period of wind waves 143136: - max_pp1ds - Time-maximum peak wave period of total swell 143137: - max_pp1d1 - Time-maximum peak wave period of first swell partition 143138: - max_pp1d2 - Time-maximum peak wave period of second swell partition 143139: - max_pp1d3 - Time-maximum peak wave period of third swell partition 143140: - max_pwd - Time-maximum peak wave direction (total) 143141: - max_pwdw - Time-maximum peak wave direction of wind waves 143142: - max_pwds - Time-maximum peak wave direction of total swell 143143: - max_pwd1 - Time-maximum peak wave direction of first swell partition 143144: - max_pwd2 - Time-maximum peak wave direction of second swell partition 143145: - max_pwd3 - Time-maximum peak wave direction of third swell partition 143146: - max_wcfr - Time-maximum whitecap fraction 143147: - max_bfi2d - Time-maximum Benjamin-Feir index 2D 143148: - max_ctc - Time-maximum crest-trough correlation 143149: - max_xwrs - Time-maximum X component of the wave radiative stress to sea ice 143150: - max_ywrs - Time-maximum Y component of the wave radiative stress to sea ice 143207: - max_wss - Time-maximum wave Spectral Skewness 143208: - max_wstar - Time-maximum free convective velocity over the oceans 143209: - max_rhoao - Time-maximum air density over the oceans 143211: - max_phiaw - Time-maximum normalized energy flux into waves 143212: - max_phioc - Time-maximum normalized energy flux into ocean 143214: - max_tauoc - Time-maximum normalized stress into ocean 143215: - max_ust - Time-maximum U-component surface stokes drift 143216: - max_vst - Time-maximum V-component surface stokes drift 143217: - max_tmax - Time-maximum period corresponding to maximum individual wave height 143218: - max_hmax - Time-maximum envelop-maximum individual wave height 143220: - max_mp1 - Time-maximum mean wave period based on first moment 143221: - max_mp2 - Time-maximum mean zero-crossing wave period 143222: - max_wdw - Time-maximum wave spectral directional width 143223: - max_p1ww - Time-maximum mean wave period based on first moment for wind waves 143224: - max_p2ww - Time-maximum mean wave period based on second moment for wind waves 143225: - max_dwww - Time-maximum wave spectral directional width for wind waves 143226: - max_p1ps - Time-maximum mean wave period based on first moment for swell 143227: - max_p2ps - Time-maximum mean wave period based on second moment for swell 143228: - max_dwps - Time-maximum wave spectral directional width for swell 143229: - max_swh - Time-maximum significant height of combined wind waves and swell 143230: - max_mwd - Time-maximum mean wave direction 143231: - max_pp1d - Time-maximum peak wave period 143232: - max_mwp - Time-maximum mean wave period 143233: - max_cdww - Time-maximum coefficient of drag with waves 143234: - max_shww - Time-maximum significant height of wind waves 143235: - max_mdww - Time-maximum mean direction of wind waves 143236: - max_mpww - Time-maximum mean period of wind waves 143237: - max_shts - Time-maximum significant height of total swell 143238: - max_mdts - Time-maximum mean direction of total swell 143239: - max_mpts - Time-maximum mean period of total swell 143244: - max_msqs - Time-maximum mean square slope of waves 143245: - max_wind - Time-maximum 10 metre wind speed 143249: - max_dwi - Time-maximum 10 metre wind direction 143252: - max_wsk - Time-maximum wave spectral kurtosis 143253: - max_bfi - Time-maximum benjamin-Feir index 143254: - max_wsp - Time-maximum wave spectral peakedness 144098: - min_weta - Time-minimum wave induced mean sea level correction 144099: - min_wraf - Time-minimum ratio of wave angular and frequency width 144100: - min_wnslc - Time-minimum number of events in freak waves statistics 144101: - min_utaua - Time-minimum U-component of atmospheric surface momentum flux 144102: - min_vtaua - Time-minimum V-component of atmospheric surface momentum flux 144103: - min_utauo - Time-minimum U-component of surface momentum flux into ocean 144104: - min_vtauo - Time-minimum V-component of surface momentum flux into ocean 144105: - min_wphio - Time-minimum wave turbulent energy flux into ocean 144106: - min_wdw1 - Time-minimum wave directional width of first swell partition 144107: - min_wfw1 - Time-minimum wave frequency width of first swell partition 144108: - min_wdw2 - Time-minimum wave directional width of second swell partition 144109: - min_wfw2 - Time-minimum wave frequency width of second swell partition 144110: - min_wdw3 - Time-minimum wave directional width of third swell partition 144111: - min_wfw3 - Time-minimum wave frequency width of third swell partition 144112: - min_wefxm - Time-minimum wave energy flux magnitude 144113: - min_wefxd - Time-minimum wave energy flux mean direction 144114: - min_h1012 - Time-minimum significant wave height of all waves with periods within the inclusive range from 10 to 12 seconds 144115: - min_h1214 - Time-minimum significant wave height of all waves with periods within the inclusive range from 12 to 14 seconds 144116: - min_h1417 - Time-minimum significant wave height of all waves with periods within the inclusive range from 14 to 17 seconds 144117: - min_h1721 - Time-minimum significant wave height of all waves with periods within the inclusive range from 17 to 21 seconds 144118: - min_h2125 - Time-minimum significant wave height of all waves with periods within the inclusive range from 21 to 25 seconds 144119: - min_h2530 - Time-minimum significant wave height of all waves with periods within the inclusive range from 25 to 30 seconds 144120: - min_sh10 - Time-minimum significant wave height of all waves with period larger than 10s 144121: - min_swh1 - Time-minimum significant wave height of first swell partition 144122: - min_mwd1 - Time-minimum mean wave direction of first swell partition 144123: - min_mwp1 - Time-minimum mean wave period of first swell partition 144124: - min_swh2 - Time-minimum significant wave height of second swell partition 144125: - min_mwd2 - Time-minimum mean wave direction of second swell partition 144126: - min_mwp2 - Time-minimum mean wave period of second swell partition 144127: - min_swh3 - Time-minimum significant wave height of third swell partition 144128: - min_mwd3 - Time-minimum mean wave direction of third swell partition 144129: - min_mwp3 - Time-minimum mean wave period of third swell partition 144131: - min_tdcmax - Time-minimum time domain maximum individual crest height 144132: - min_tdhmax - Time-minimum time domain maximum individual wave height 144133: - min_stcmax - Time-minimum space time maximum individual crest height 144134: - min_sthmax - Time-minimum space time maximum individual wave height 144135: - min_pp1dw - Time-minimum peak wave period of wind waves 144136: - min_pp1ds - Time-minimum peak wave period of total swell 144137: - min_pp1d1 - Time-minimum peak wave period of first swell partition 144138: - min_pp1d2 - Time-minimum peak wave period of second swell partition 144139: - min_pp1d3 - Time-minimum peak wave period of third swell partition 144140: - min_pwd - Time-minimum peak wave direction (total) 144141: - min_pwdw - Time-minimum peak wave direction of wind waves 144142: - min_pwds - Time-minimum peak wave direction of total swell 144143: - min_pwd1 - Time-minimum peak wave direction of first swell partition 144144: - min_pwd2 - Time-minimum peak wave direction of second swell partition 144145: - min_pwd3 - Time-minimum peak wave direction of third swell partition 144146: - min_wcfr - Time-minimum whitecap fraction 144147: - min_bfi2d - Time-minimum Benjamin-Feir index 2D 144148: - min_ctc - Time-minimum crest-trough correlation 144149: - min_xwrs - Time-minimum X component of the wave radiative stress to sea ice 144150: - min_ywrs - Time-minimum Y component of the wave radiative stress to sea ice 144207: - min_wss - Time-minimum wave Spectral Skewness 144208: - min_wstar - Time-minimum free convective velocity over the oceans 144209: - min_rhoao - Time-minimum air density over the oceans 144211: - min_phiaw - Time-minimum normalized energy flux into waves 144212: - min_phioc - Time-minimum normalized energy flux into ocean 144214: - min_tauoc - Time-minimum normalized stress into ocean 144215: - min_ust - Time-minimum U-component surface stokes drift 144216: - min_vst - Time-minimum V-component surface stokes drift 144217: - min_tmax - Time-minimum period corresponding to maximum individual wave height 144218: - min_hmax - Time-minimum envelop-maximum individual wave height 144220: - min_mp1 - Time-minimum mean wave period based on first moment 144221: - min_mp2 - Time-minimum mean zero-crossing wave period 144222: - min_wdw - Time-minimum wave spectral directional width 144223: - min_p1ww - Time-minimum mean wave period based on first moment for wind waves 144224: - min_p2ww - Time-minimum mean wave period based on second moment for wind waves 144225: - min_dwww - Time-minimum wave spectral directional width for wind waves 144226: - min_p1ps - Time-minimum mean wave period based on first moment for swell 144227: - min_p2ps - Time-minimum mean wave period based on second moment for swell 144228: - min_dwps - Time-minimum wave spectral directional width for swell 144229: - min_swh - Time-minimum significant height of combined wind waves and swell 144230: - min_mwd - Time-minimum mean wave direction 144231: - min_pp1d - Time-minimum peak wave period 144232: - min_mwp - Time-minimum mean wave period 144233: - min_cdww - Time-minimum coefficient of drag with waves 144234: - min_shww - Time-minimum significant height of wind waves 144235: - min_mdww - Time-minimum mean direction of wind waves 144236: - min_mpww - Time-minimum mean period of wind waves 144237: - min_shts - Time-minimum significant height of total swell 144238: - min_mdts - Time-minimum mean direction of total swell 144239: - min_mpts - Time-minimum mean period of total swell 144244: - min_msqs - Time-minimum mean square slope of waves 144245: - min_wind - Time-minimum 10 metre wind speed 144249: - min_dwi - Time-minimum 10 metre wind direction 144252: - min_wsk - Time-minimum wave spectral kurtosis 144253: - min_bfi - Time-minimum benjamin-Feir index 144254: - min_wsp - Time-minimum wave spectral peakedness 145098: - std_weta - Time-standard-deviation wave induced mean sea level correction 145099: - std_wraf - Time-standard-deviation ratio of wave angular and frequency width 145100: - std_wnslc - Time-standard-deviation number of events in freak waves statistics 145101: - std_utaua - Time-standard-deviation U-component of atmospheric surface momentum flux 145102: - std_vtaua - Time-standard-deviation V-component of atmospheric surface momentum flux 145103: - std_utauo - Time-standard-deviation U-component of surface momentum flux into ocean 145104: - std_vtauo - Time-standard-deviation V-component of surface momentum flux into ocean 145105: - std_wphio - Time-standard-deviation wave turbulent energy flux into ocean 145106: - std_wdw1 - Time-standard-deviation wave directional width of first swell partition 145107: - std_wfw1 - Time-standard-deviation wave frequency width of first swell partition 145108: - std_wdw2 - Time-standard-deviation wave directional width of second swell partition 145109: - std_wfw2 - Time-standard-deviation wave frequency width of second swell partition 145110: - std_wdw3 - Time-standard-deviation wave directional width of third swell partition 145111: - std_wfw3 - Time-standard-deviation wave frequency width of third swell partition 145112: - std_wefxm - Time-standard-deviation wave energy flux magnitude 145113: - std_wefxd - Time-standard-deviation wave energy flux mean direction 145114: - std_h1012 - Time-standard-deviation significant wave height of all waves with periods within the inclusive range from 10 to 12 seconds 145115: - std_h1214 - Time-standard-deviation significant wave height of all waves with periods within the inclusive range from 12 to 14 seconds 145116: - std_h1417 - Time-standard-deviation significant wave height of all waves with periods within the inclusive range from 14 to 17 seconds 145117: - std_h1721 - Time-standard-deviation significant wave height of all waves with periods within the inclusive range from 17 to 21 seconds 145118: - std_h2125 - Time-standard-deviation significant wave height of all waves with periods within the inclusive range from 21 to 25 seconds 145119: - std_h2530 - Time-standard-deviation significant wave height of all waves with periods within the inclusive range from 25 to 30 seconds 145120: - std_sh10 - Time-standard-deviation significant wave height of all waves with period larger than 10s 145121: - std_swh1 - Time-standard-deviation significant wave height of first swell partition 145122: - std_mwd1 - Time-standard-deviation mean wave direction of first swell partition 145123: - std_mwp1 - Time-standard-deviation mean wave period of first swell partition 145124: - std_swh2 - Time-standard-deviation significant wave height of second swell partition 145125: - std_mwd2 - Time-standard-deviation mean wave direction of second swell partition 145126: - std_mwp2 - Time-standard-deviation mean wave period of second swell partition 145127: - std_swh3 - Time-standard-deviation significant wave height of third swell partition 145128: - std_mwd3 - Time-standard-deviation mean wave direction of third swell partition 145129: - std_mwp3 - Time-standard-deviation mean wave period of third swell partition 145131: - std_tdcmax - Time-standard-deviation time domain maximum individual crest height 145132: - std_tdhmax - Time-standard-deviation time domain maximum individual wave height 145133: - std_stcmax - Time-standard-deviation space time maximum individual crest height 145134: - std_sthmax - Time-standard-deviation space time maximum individual wave height 145135: - std_pp1dw - Time-standard-deviation peak wave period of wind waves 145136: - std_pp1ds - Time-standard-deviation peak wave period of total swell 145137: - std_pp1d1 - Time-standard-deviation peak wave period of first swell partition 145138: - std_pp1d2 - Time-standard-deviation peak wave period of second swell partition 145139: - std_pp1d3 - Time-standard-deviation peak wave period of third swell partition 145140: - std_pwd - Time-standard-deviation peak wave direction (total) 145141: - std_pwdw - Time-standard-deviation peak wave direction of wind waves 145142: - std_pwds - Time-standard-deviation peak wave direction of total swell 145143: - std_pwd1 - Time-standard-deviation peak wave direction of first swell partition 145144: - std_pwd2 - Time-standard-deviation peak wave direction of second swell partition 145145: - std_pwd3 - Time-standard-deviation peak wave direction of third swell partition 145146: - std_wcfr - Time-standard-deviation whitecap fraction 145147: - std_bfi2d - Time-standard-deviation Benjamin-Feir index 2D 145148: - std_ctc - Time-standard-deviation crest-trough correlation 145149: - std_xwrs - Time-standard-deviation X component of the wave radiative stress to sea ice 145150: - std_ywrs - Time-standard-deviation Y component of the wave radiative stress to sea ice 145207: - std_wss - Time-standard-deviation wave Spectral Skewness 145208: - std_wstar - Time-standard-deviation free convective velocity over the oceans 145209: - std_rhoao - Time-standard-deviation air density over the oceans 145211: - std_phiaw - Time-standard-deviation normalized energy flux into waves 145212: - std_phioc - Time-standard-deviation normalized energy flux into ocean 145214: - std_tauoc - Time-standard-deviation normalized stress into ocean 145215: - std_ust - Time-standard-deviation U-component surface stokes drift 145216: - std_vst - Time-standard-deviation V-component surface stokes drift 145217: - std_tmax - Time-standard-deviation period corresponding to maximum individual wave height 145218: - std_hmax - Time-standard-deviation envelop-maximum individual wave height 145220: - std_mp1 - Time-standard-deviation mean wave period based on first moment 145221: - std_mp2 - Time-standard-deviation mean zero-crossing wave period 145222: - std_wdw - Time-standard-deviation wave spectral directional width 145223: - std_p1ww - Time-standard-deviation mean wave period based on first moment for wind waves 145224: - std_p2ww - Time-standard-deviation mean wave period based on second moment for wind waves 145225: - std_dwww - Time-standard-deviation wave spectral directional width for wind waves 145226: - std_p1ps - Time-standard-deviation mean wave period based on first moment for swell 145227: - std_p2ps - Time-standard-deviation mean wave period based on second moment for swell 145228: - std_dwps - Time-standard-deviation wave spectral directional width for swell 145229: - std_swh - Time-standard-deviation significant height of combined wind waves and swell 145230: - std_mwd - Time-standard-deviation mean wave direction 145231: - std_pp1d - Time-standard-deviation peak wave period 145232: - std_mwp - Time-standard-deviation mean wave period 145233: - std_cdww - Time-standard-deviation coefficient of drag with waves 145234: - std_shww - Time-standard-deviation significant height of wind waves 145235: - std_mdww - Time-standard-deviation mean direction of wind waves 145236: - std_mpww - Time-standard-deviation mean period of wind waves 145237: - std_shts - Time-standard-deviation significant height of total swell 145238: - std_mdts - Time-standard-deviation mean direction of total swell 145239: - std_mpts - Time-standard-deviation mean period of total swell 145244: - std_msqs - Time-standard-deviation mean square slope of waves 145245: - std_wind - Time-standard-deviation 10 metre wind speed 145249: - std_dwi - Time-standard-deviation 10 metre wind direction 145252: - std_wsk - Time-standard-deviation wave spectral kurtosis 145253: - std_bfi - Time-standard-deviation benjamin-Feir index 145254: - std_wsp - Time-standard-deviation wave spectral peakedness 150129: - ocpt - Ocean potential temperature 150130: - ocs - Ocean salinity 150131: - ocpd - Ocean potential density 150133: - _param_150133 - Ocean U wind component 150134: - _param_150134 - Ocean V wind component 150135: - ocw - Ocean W wind component 150137: - rn - Richardson number 150139: - uv - U*V product 150140: - ut - U*T product 150141: - vt - V*T product 150142: - uu - U*U product 150143: - vv - V*V product 150144: - _param_150144 - UV - U~V~ 150145: - _param_150145 - UT - U~T~ 150146: - _param_150146 - VT - V~T~ 150147: - _param_150147 - UU - U~U~ 150148: - _param_150148 - VV - V~V~ 150152: - sl - Sea level 150153: - _param_150153 - Barotropic stream function 150154: - mld - Mixed layer depth 150155: - _param_150155 - Depth 150168: - _param_150168 - U stress 150169: - _param_150169 - V stress 150170: - _param_150170 - Turbulent kinetic energy input 150171: - nsf - Net surface heat flux 150172: - _param_150172 - Surface solar radiation 150173: - _param_150173 - P-E 150180: - _param_150180 - Diagnosed sea surface temperature error 150181: - _param_150181 - Heat flux correction 150182: - _param_150182 - Observed sea surface temperature 150183: - _param_150183 - Observed heat flux 150255: - _param_150255 - Indicates a missing value 151126: - mswpt300m - Mean sea water potential temperature in the upper 300 m 151127: - mswt300m - Mean sea water temperature in the upper 300 m 151128: - _param_151128 - In situ Temperature 151129: - thetao - Sea water potential temperature 151130: - so - Sea water practical salinity 151131: - ocu - Eastward surface sea water velocity 151132: - ocv - Northward surface sea water velocity 151133: - wo - Upward sea water velocity 151134: - mst - Modulus of strain rate tensor 151135: - vvs - Vertical viscosity 151136: - vdf - Vertical diffusivity 151137: - dep - Bottom level Depth 151138: - sigmat - Sea water sigma theta 151139: - rn - Richardson number 151140: - uv - UV product 151141: - ut - UT product 151142: - vt - VT product 151143: - uu - UU product 151144: - vv - VV product 151145: - zos - Sea surface height 151146: - sl_1 - Sea level previous timestep 151147: - stfbarot - Ocean barotropic stream function 151148: - mld - Mixed layer depth 151149: - btp - Bottom Pressure (equivalent height) 151150: - sh - Steric height 151151: - crl - Curl of Wind Stress 151152: - _param_151152 - Divergence of wind stress 151153: - taueo - Surface downward eastward stress 151154: - tauno - Surface downward northward stress 151155: - tki - Turbulent kinetic energy input 151156: - nsf - Net surface heat flux 151157: - asr - Absorbed solar radiation 151158: - pme - Precipitation - evaporation 151159: - sst - Specified sea surface temperature 151160: - shf - Specified surface heat flux 151161: - dte - Diagnosed sea surface temperature error 151162: - hfc - Heat flux correction 151163: - t20d - Depth of 20C isotherm 151164: - tav300 - Average potential temperature in the upper 300m 151165: - uba1 - Vertically integrated zonal velocity (previous time step) 151166: - vba1 - Vertically Integrated meridional velocity (previous time step) 151167: - ztr - Vertically integrated zonal volume transport 151168: - mtr - Vertically integrated meridional volume transport 151169: - zht - Vertically integrated zonal heat transport 151170: - mht - Vertically integrated meridional heat transport 151171: - umax - U velocity maximum 151172: - dumax - Depth of the velocity maximum 151173: - smax - Salinity maximum 151174: - dsmax - Depth of salinity maximum 151175: - sav300 - Average sea water practical salinity in the upper 300m 151176: - ldp - Layer Thickness at scalar points 151177: - ldu - Layer Thickness at vector points 151178: - pti - Potential temperature increment 151179: - ptae - Potential temperature analysis error 151180: - bpt - Background potential temperature 151181: - apt - Analysed potential temperature 151182: - ptbe - Potential temperature background error 151183: - as - Analysed salinity 151184: - sali - Salinity increment 151185: - ebt - Estimated Bias in Temperature 151186: - ebs - Estimated Bias in Salinity 151187: - uvi - Zonal Velocity increment (from balance operator) 151188: - vvi - Meridional Velocity increment (from balance operator) 151189: - tos - Sea surface temperature in degC 151190: - subi - Salinity increment (from salinity data) 151191: - sale - Salinity analysis error 151192: - bsal - Background Salinity 151193: - _param_151193 - Reserved 151194: - salbe - Salinity background error 151195: - t14d - Depth of 14C isotherm 151196: - t17d - Depth of 17C isotherm 151197: - t26d - Depth of 26C isotherm 151198: - t28d - Depth of 28C isotherm 151199: - ebta - Estimated temperature bias from assimilation 151200: - ebsa - Estimated salinity bias from assimilation 151201: - lti - Temperature increment from relaxation term 151202: - lsi - Salinity increment from relaxation term 151203: - bzpga - Bias in the zonal pressure gradient (applied) 151204: - bmpga - Bias in the meridional pressure gradient (applied) 151205: - ebtl - Estimated temperature bias from relaxation 151206: - ebsl - Estimated salinity bias from relaxation 151207: - fgbt - First guess bias in temperature 151208: - fgbs - First guess bias in salinity 151209: - bpa - Applied bias in pressure 151210: - fgbp - FG bias in pressure 151211: - pta - Bias in temperature(applied) 151212: - psa - Bias in salinity (applied) 151213: - hfds - Surface downward heat flux in sea water 151214: - hc300m - Ocean heat content 0-300m 151215: - hc700m - Ocean heat content 0-700m 151216: - hcbtm - Ocean heat content 0-bottom 151217: - wfcorr - Water flux correction 151219: - sos - Sea surface practical salinity 151222: - tauvo - Surface downward y stress 151223: - tauuo - Surface downward x stress 151224: - mlotdev - Ocean mixed layer thickness defined by vertical tracer diffusivity threshold 151225: - mlotst010 - Ocean mixed layer thickness defined by sigma theta 0.01 kg/m3 151226: - mlotst030 - Ocean mixed layer thickness defined by sigma theta 0.03 kg/m3 151227: - mlotst125 - Ocean mixed layer thickness defined by sigma theta 0.125 kg/m3 151228: - mlott02 - Ocean mixed layer thickness defined by temperature 0.2C 151229: - mlott05 - Ocean mixed layer thickness defined by temperature 0.5C 151230: - vsf - Virtual salt flux into sea water 151232: - sc700m - Integrated salinity 0-700m 151233: - sabtm - Integrated salinity 0-bottom 151234: - swmth - Sea water mass per unit area expressed as thickness 151235: - sc300m - Integrated salinity 0-300m 151236: - rss - Surface net downward shortwave flux into ocean 151250: - voy - Sea water y velocity 151251: - uox - Sea water x velocity 151255: - _param_151255 - Indicates a missing value 160049: - 10fgrea - 10 metre wind gust during averaging time 160135: - wrea - vertical velocity (pressure) 160137: - pwcrea - Precipitable water content 160140: - swl1rea - Soil wetness level 1 160141: - sdrea - Snow depth 160142: - lsprea - Large-scale precipitation 160143: - cprea - Convective precipitation 160144: - sfrea - Snowfall 160156: - ghrea - Height 160157: - rrea - Relative humidity 160171: - swl2rea - Soil wetness level 2 160180: - ewssrea - East-West surface stress 160181: - nsssrea - North-South surface stress 160182: - erea - Evaporation 160184: - swl3rea - Soil wetness level 3 160198: - srcon - Skin reservoir content 160199: - vegrea - Percentage of vegetation 160205: - rorea - Runoff 160207: - tzrea - Covariance of temperature and geopotential 160209: - qzrea - Covariance of specific humidity and geopotential 160210: - qtrea - Covariance of specific humidity and temperature 160212: - uzrea - Covariance of U component and geopotential 160213: - utrea - Covariance of U component and temperature 160214: - uqrea - Covariance of U component and specific humidity 160216: - vzrea - Covariance of V component and geopotential 160217: - vtrea - Covariance of V component and temperature 160218: - vqrea - Covariance of V component and specific humidity 160219: - vurea - Covariance of V component and U component 160221: - wzrea - Covariance of W component and geopotential 160222: - wtrea - Covariance of W component and temperature 160223: - wqrea - Covariance of W component and specific humidity 160224: - wurea - Covariance of W component and U component 160225: - wvrea - Covariance of W component and V component 160231: - ishfrea - Instantaneous surface heat flux 160239: - csfrea - Convective snowfall 160240: - lsfrea - Large scale snowfall 160241: - clwcerrea - Cloud liquid water content 160242: - ccrea - Cloud cover 160243: - falrea - Forecast albedo 160246: - 10wsrea - 10 metre wind speed 160247: - moflrea - Momentum flux 160249: - _param_160249 - Gravity wave dissipation flux 160254: - hsdrea - Heaviside beta function 162031: - viwgd - Total column vertically-integrated divergence of water geopotential flux 162032: - viee - Total column vertically-integrated eastward enthalpy flux 162033: - vien - Total column vertically-integrated northward enthalpy flux 162034: - vied - Total column vertically-integrated divergence of enthalpy flux 162035: - viwed - Total column vertically-integrated divergence of water enthalpy flux 162036: - viwvd - Total column vertically-integrated divergence of water vapour flux 162037: - viclwd - Total column vertically-integrated divergence of cloud liquid water flux 162038: - viciwd - Total column vertically-integrated divergence of cloud ice water flux 162039: - vird - Total column vertically-integrated divergence of rain flux 162040: - visd - Total column vertically-integrated divergence of snow flux 162041: - viclwe - Total column vertically-integrated eastward cloud liquid water flux 162042: - viclwn - Total column vertically-integrated northward cloud liquid water flux 162043: - viciwe - Total column vertically-integrated eastward cloud ice water flux 162044: - viciwn - Total column vertically-integrated northward cloud ice water flux 162045: - wvf - Water vapour flux 162046: - vire - Total column vertically-integrated eastward rain flux 162047: - virn - Total column vertically-integrated northward rain flux 162048: - vise - Total column vertically-integrated eastward snow flux 162049: - visn - Total column vertically-integrated northward snow flux 162050: - vions - Total column vertically-integrated net source of ozone 162051: - _param_162051 - Surface geopotential 162053: - vima - Total column vertically-integrated mass of atmosphere 162054: - vit - Total column vertically-integrated temperature 162055: - viwv - Total column vertically-integrated water vapour 162056: - vilw - Total column vertically-integrated cloud liquid water 162057: - viiw - Total column vertically-integrated cloud frozen water 162058: - vioz - Total column vertically-integrated ozone 162059: - vike - Total column vertically-integrated kinetic energy 162060: - vithe - Total column vertically-integrated enthalpy 162061: - vipie - Total column vertically-integrated potential + internal energy 162062: - vipile - Total column vertically-integrated potential+internal+latent energy 162063: - vitoe - Total column vertically-integrated total energy 162064: - viec - Total column vertically-integrated energy conversion 162065: - vimae - Total column vertically-integrated eastward mass flux 162066: - viman - Total column vertically-integrated northward mass flux 162067: - vikee - Total column vertically-integrated eastward kinetic energy flux 162068: - viken - Total column vertically-integrated northward kinetic energy flux 162069: - vithee - Total column vertically-integrated eastward heat flux 162070: - vithen - Total column vertically-integrated northward heat flux 162071: - viwve - Total column vertically-integrated eastward water vapour flux 162072: - viwvn - Total column vertically-integrated northward water vapour flux 162073: - vige - Total column vertically-integrated eastward geopotential flux 162074: - vign - Total column vertically-integrated northward geopotential flux 162075: - vitee - Total column vertically-integrated eastward total energy flux 162076: - viten - Total column vertically-integrated northward total energy flux 162077: - vioze - Total column vertically-integrated eastward ozone flux 162078: - viozn - Total column vertically-integrated northward ozone flux 162079: - vilwd - Total column vertically-integrated divergence of cloud liquid water flux 162080: - viiwd - Total column vertically-integrated divergence of cloud frozen water flux 162081: - vimad - Total column vertically-integrated divergence of mass flux 162082: - viked - Total column vertically-integrated divergence of kinetic energy flux 162083: - vithed - Total column vertically-integrated divergence of thermal energy flux 162084: - vimdf - Total column vertically-integrated moisture divergence flux 162085: - vigd - Total column vertically-integrated divergence of geopotential flux 162086: - vited - Total column vertically-integrated divergence of total energy flux 162087: - viozd - Total column vertically-integrated divergence of ozone flux 162088: - vilwe - Total column vertically-integrated eastward cloud liquid water flux 162089: - vilwn - Total column vertically-integrated northward cloud liquid water flux 162090: - viiwe - Total column vertically-integrated eastward cloud frozen water flux 162091: - viiwn - Total column vertically-integrated northward cloud frozen water flux 162092: - vimat - Total column vertically-integrated mass tendency 162093: - viwe - Total column vertically-integrated water enthalpy 162100: - srta - Time-integrated temperature tendency due to short-wave radiation 162101: - trta - Time-integrated temperature tendency due to long-wave radiation 162102: - srtca - Time-integrated temperature tendency due to short wave radiation, clear sky 162103: - trtca - Time-integrated temperature tendency due to long-wave radiation, clear sky 162104: - umfa - Time-integrated updraught mass flux 162105: - dmfa - Time-integrated downdraught mass flux 162106: - udra - Time-integrated updraught detrainment rate 162107: - ddra - Time-integrated downdraught detrainment rate 162108: - tpfa - Time-integrated total precipitation flux 162109: - tdcha - Time-integrated turbulent diffusion coefficient for heat 162110: - ttpha - Time-integrated temperature tendency due to parametrisations 162111: - qtpha - Time-integrated specific humidity tendency due to parametrisations 162112: - utpha - Time-integrated eastward wind tendency due to parametrisations 162113: - vtpha - Time-integrated northward wind tendency due to parametrisations 162114: - utendd - U-tendency from dynamics 162115: - vtendd - V-tendency from dynamics 162116: - ttendd - T-tendency from dynamics 162117: - qtendd - q-tendency from dynamics 162118: - ttendr - T-tendency from radiation 162119: - utendts - U-tendency from turbulent diffusion + subgrid orography 162120: - vtendts - V-tendency from turbulent diffusion + subgrid orography 162121: - ttendts - T-tendency from turbulent diffusion + subgrid orography 162122: - qtendt - q-tendency from turbulent diffusion 162123: - utends - U-tendency from subgrid orography 162124: - vtends - V-tendency from subgrid orography 162125: - ttends - T-tendency from subgrid orography 162126: - utendcds - U-tendency from convection (deep+shallow) 162127: - vtendcds - V-tendency from convection (deep+shallow) 162128: - ttendcds - T-tendency from convection (deep+shallow) 162129: - qtendcds - q-tendency from convection (deep+shallow) 162130: - lpc - Liquid Precipitation flux from convection 162131: - ipc - Ice Precipitation flux from convection 162132: - ttendcs - T-tendency from cloud scheme 162133: - qtendcs - q-tendency from cloud scheme 162134: - qltendcs - ql-tendency from cloud scheme 162135: - qitendcs - qi-tendency from cloud scheme 162136: - lpcs - Liquid Precip flux from cloud scheme (stratiform) 162137: - ipcs - Ice Precip flux from cloud scheme (stratiform) 162138: - utendcs - U-tendency from shallow convection 162139: - vtendcs - V-tendency from shallow convection 162140: - ttendsc - T-tendency from shallow convection 162141: - qtendsc - q-tendency from shallow convection 162150: - ttswr - Temperature tendency due to short-wave radiation 162151: - ttlwr - Temperature tendency due to long-wave radiation 162152: - ttswrcs - Temperature tendency due to short-wave radiation, clear sky 162153: - ttlwrcs - Temperature tendency due to long-wave radiation, clear sky 162154: - umf - Updraught mass flux 162155: - dmf - Downdraught mass flux 162156: - udr - Updraught detrainment rate 162157: - ddr - Downdraught detrainment rate 162158: - tpf - Total precipitation flux 162159: - tdch - Turbulent diffusion coefficient for heat 162160: - ttpm - Temperature tendency due to parametrisations 162161: - qtpm - Specific humidity tendency due to parametrisations 162162: - utpm - Eastward wind tendency due to parametrisations 162163: - vtpm - Northward wind tendency due to parametrisations 162206: - _param_162206 - Variance of geopotential 162207: - _param_162207 - Covariance of geopotential/temperature 162208: - _param_162208 - Variance of temperature 162209: - _param_162209 - Covariance of geopotential/specific humidity 162210: - _param_162210 - Covariance of temperature/specific humidity 162211: - _param_162211 - Variance of specific humidity 162212: - _param_162212 - Covariance of u component/geopotential 162213: - _param_162213 - Covariance of u component/temperature 162214: - _param_162214 - Covariance of u component/specific humidity 162215: - _param_162215 - Variance of u component 162216: - _param_162216 - Covariance of v component/geopotential 162217: - _param_162217 - Covariance of v component/temperature 162218: - _param_162218 - Covariance of v component/specific humidity 162219: - _param_162219 - Covariance of v component/u component 162220: - _param_162220 - Variance of v component 162221: - _param_162221 - Covariance of omega/geopotential 162222: - _param_162222 - Covariance of omega/temperature 162223: - _param_162223 - Covariance of omega/specific humidity 162224: - _param_162224 - Covariance of omega/u component 162225: - _param_162225 - Covariance of omega/v component 162226: - _param_162226 - Variance of omega 162227: - _param_162227 - Variance of surface pressure 162229: - _param_162229 - Variance of relative humidity 162230: - _param_162230 - Covariance of u component/ozone 162231: - _param_162231 - Covariance of v component/ozone 162232: - _param_162232 - Covariance of omega/ozone 162233: - _param_162233 - Variance of ozone 162255: - _param_162255 - Indicates a missing value 170001: - spi03 - Standardised precipitation index valid in the last 3 months 170002: - spi06 - Standardised precipitation index valid in the last 6 months 170003: - spi12 - Standardised precipitation index valid in the last 12 months 170149: - tsw - Total soil moisture 170171: - swl2 - Soil wetness level 2 170179: - ttr - Top net thermal radiation 171001: - strfa - Stream function anomaly 171002: - vpota - Velocity potential anomaly 171003: - pta - Potential temperature anomaly 171004: - epta - Equivalent potential temperature anomaly 171005: - septa - Saturated equivalent potential temperature anomaly 171006: - 100ua - 100 metre U wind component anomaly 171007: - 100va - 100 metre V wind component anomaly 171008: - 100sia - 100 metre wind speed anomaly 171011: - udwa - U component of divergent wind anomaly 171012: - vdwa - V component of divergent wind anomaly 171013: - urwa - U component of rotational wind anomaly 171014: - vrwa - V component of rotational wind anomaly 171021: - uctpa - Unbalanced component of temperature anomaly 171022: - uclna - Unbalanced component of logarithm of surface pressure anomaly 171023: - ucdva - Unbalanced component of divergence anomaly 171024: - lmlta - Lake mix-layer temperature anomaly 171025: - licda - Lake ice depth anomaly 171026: - cla - Lake cover anomaly 171027: - cvla - Low vegetation cover anomaly 171028: - cvha - High vegetation cover anomaly 171029: - tvla - Type of low vegetation anomaly 171030: - tvha - Type of high vegetation anomaly 171031: - sica - Sea-ice cover anomaly - ci 171032: - asna - Snow albedo anomaly 171033: - rsna - Snow density anomaly 171034: - ssta - Sea surface temperature anomaly 171035: - istal1 - Ice surface temperature anomaly layer 1 171036: - istal2 - Ice surface temperature anomaly layer 2 171037: - istal3 - Ice surface temperature anomaly layer 3 171038: - istal4 - Ice surface temperature anomaly layer 4 171039: - swval1 - Volumetric soil water anomaly layer 1 - swv1 - swvl1a 171040: - swval2 - Volumetric soil water anomaly layer 2 - swv2 - swvl2a 171041: - swval3 - Volumetric soil water anomaly layer 3 - swv3 - swvl3a 171042: - swval4 - Volumetric soil water anomaly layer 4 - swv4 - swvl4a 171043: - slta - Soil type anomaly 171044: - esa - Snow evaporation anomaly 171045: - smlta - Snowmelt anomaly 171046: - sdura - Solar duration anomaly 171047: - dsrpa - Direct solar radiation anomaly 171048: - magssa - Magnitude of turbulent surface stress anomaly 171049: - 10fga - 10 metre wind gust anomaly 171050: - lspfa - Large-scale precipitation fraction anomaly 171051: - mx2t24a - Maximum 2 metre temperature in the last 24 hours anomaly 171052: - mn2t24a - Minimum 2 metre temperature in the last 24 hours anomaly 171053: - monta - Montgomery potential anomaly 171054: - pa - Pressure anomaly 171055: - mean2t24a - Mean 2 metre temperature in the last 24 hours anomaly 171056: - mn2d24a - Mean 2 metre dewpoint temperature in the last 24 hours anomaly 171057: - uvba - Downward UV radiation at the surface anomaly 171058: - para - Photosynthetically active radiation at the surface anomaly 171059: - capea - Convective available potential energy anomaly 171060: - pva - Potential vorticity anomaly 171061: - tpoa - Total precipitation from observations anomaly 171062: - obcta - Observation count anomaly 171063: - stsktda - Start time for skin temperature difference anomaly 171064: - ftsktda - Finish time for skin temperature difference anomaly 171065: - sktda - Skin temperature difference anomaly 171078: - tclwa - Total column liquid water anomaly 171079: - tciwa - Total column ice water anomaly 171121: - mx2t6a - Maximum temperature at 2 metres in the last 6 hours anomaly 171122: - mn2t6a - Minimum temperature at 2 metres in the last 6 hours anomaly 171125: - vitea - Vertically integrated total energy anomaly 171126: - _param_171126 - Generic parameter for sensitive area prediction 171127: - ata - Atmospheric tide anomaly 171128: - bva - Budget values anomaly 171129: - za - Geopotential anomaly - z 171130: - ta - Temperature anomaly - t 171131: - ua - U component of wind anomaly - u 171132: - va - V component of wind anomaly - v 171133: - qa - Specific humidity anomaly 171134: - spa - Surface pressure anomaly 171135: - wa - Vertical velocity (pressure) anomaly 171136: - tcwa - Total column water anomaly 171137: - tcwva - Total column water vapour anomaly 171138: - voa - Relative vorticity anomaly - vo 171139: - stal1 - Soil temperature anomaly level 1 - stl1 - st 171140: - swal1 - Soil wetness anomaly level 1 - swl1 171141: - sda - Snow depth anomaly 171142: - lspa - Stratiform precipitation (Large-scale precipitation) anomaly 171143: - cpa - Convective precipitation anomaly 171144: - sfa - Snowfall (convective + stratiform) anomaly 171145: - blda - Boundary layer dissipation anomaly 171146: - sshfa - Surface sensible heat flux anomaly 171147: - slhfa - Surface latent heat flux anomaly 171148: - chnka - Charnock anomaly 171149: - snra - Surface net radiation anomaly 171150: - tnra - Top net radiation anomaly 171151: - msla - Mean sea level pressure anomaly - msl 171152: - lspa - Logarithm of surface pressure anomaly 171153: - swhra - Short-wave heating rate anomaly 171154: - lwhra - Long-wave heating rate anomaly 171155: - da - Relative divergence anomaly - d 171156: - gha - Height anomaly - gh 171157: - ra - Relative humidity anomaly - r 171158: - tspa - Tendency of surface pressure anomaly 171159: - blha - Boundary layer height anomaly 171160: - sdora - Standard deviation of orography anomaly 171161: - isora - Anisotropy of sub-gridscale orography anomaly 171162: - anora - Angle of sub-gridscale orography anomaly 171163: - slora - Slope of sub-gridscale orography anomaly 171164: - tcca - Total cloud cover anomaly 171165: - 10ua - 10 metre U wind component anomaly 171166: - 10va - 10 metre V wind component anomaly 171167: - 2ta - 2 metre temperature anomaly 171168: - 2da - 2 metre dewpoint temperature anomaly 171169: - ssrda - Surface solar radiation downwards anomaly 171170: - stal2 - Soil temperature anomaly level 2 - slal2 - stl2 171171: - swal2 - Soil wetness anomaly level 2 - swl2 171173: - sra - Surface roughness anomaly 171174: - ala - Albedo anomaly 171175: - strda - Surface thermal radiation downwards anomaly 171176: - ssra - Surface net solar radiation anomaly 171177: - stra - Surface net thermal radiation anomaly 171178: - tsra - Top net solar radiation anomaly 171179: - ttra - Top net thermal radiation anomaly 171180: - eqssa - East-West surface stress anomaly 171181: - nsssa - North-South surface stress anomaly 171182: - ea - Evaporation anomaly 171183: - stal3 - Soil temperature anomaly level 3 - stl3 171184: - swal3 - Soil wetness anomaly level 3 - swl3 171185: - ccca - Convective cloud cover anomaly 171186: - lcca - Low cloud cover anomaly 171187: - mcca - Medium cloud cover anomaly 171188: - hcca - High cloud cover anomaly 171189: - sunda - Sunshine duration anomaly 171190: - ewova - East-West component of sub-gridscale orographic variance anomaly 171191: - nsova - North-South component of sub-gridscale orographic variance anomaly 171192: - nwova - North-West/South-East component of sub-gridscale orographic variance anomaly 171193: - neova - North-East/South-West component of sub-gridscale orographic variance anomaly 171194: - btmpa - Brightness temperature anomaly 171195: - lgwsa - Longitudinal component of gravity wave stress anomaly 171196: - mgwsa - Meridional component of gravity wave stress anomaly 171197: - gwda - Gravity wave dissipation anomaly 171198: - srca - Skin reservoir content anomaly 171199: - vfa - Vegetation fraction anomaly 171200: - vsoa - Variance of sub-gridscale orography anomaly 171201: - mx2ta - Maximum temperature at 2 metres anomaly 171202: - mn2ta - Minimum temperature at 2 metres anomaly 171203: - o3a - Ozone mass mixing ratio anomaly 171204: - pawa - Precipitation analysis weights anomaly 171205: - roa - Runoff anomaly 171206: - tco3a - Total column ozone anomaly 171207: - 10sia - 10 metre wind speed anomaly - 10si 171208: - tsrca - Top net solar radiation clear sky anomaly 171209: - ttrca - Top net thermal radiation clear sky anomaly 171210: - ssrca - Surface net solar radiation clear sky anomaly 171211: - strca - Surface net thermal radiation, clear sky anomaly 171212: - sia - Solar insolation anomaly 171214: - dhra - Diabatic heating by radiation anomaly 171215: - dhvda - Diabatic heating by vertical diffusion anomaly 171216: - dhcca - Diabatic heating by cumulus convection anomaly 171217: - dhlca - Diabatic heating by large-scale condensation anomaly 171218: - vdzwa - Vertical diffusion of zonal wind anomaly 171219: - vdmwa - Vertical diffusion of meridional wind anomaly 171220: - ewgda - East-West gravity wave drag tendency anomaly 171221: - nsgda - North-South gravity wave drag tendency anomaly 171222: - ctzwa - Convective tendency of zonal wind anomaly 171223: - ctmwa - Convective tendency of meridional wind anomaly 171224: - vdha - Vertical diffusion of humidity anomaly 171225: - htcca - Humidity tendency by cumulus convection anomaly 171226: - htlca - Humidity tendency by large-scale condensation anomaly 171227: - crnha - Change from removal of negative humidity anomaly 171228: - tpa - Total precipitation anomaly 171229: - iewsa - Instantaneous X surface stress anomaly 171230: - inssa - Instantaneous Y surface stress anomaly 171231: - ishfa - Instantaneous surface heat flux anomaly 171232: - iea - Instantaneous moisture flux anomaly 171233: - asqa - Apparent surface humidity anomaly 171234: - lsrha - Logarithm of surface roughness length for heat anomaly 171235: - skta - Skin temperature anomaly 171236: - stal4 - Soil temperature level 4 anomaly 171237: - swal4 - Soil wetness level 4 anomaly - swl4 171238: - tsna - Temperature of snow layer anomaly 171239: - csfa - Convective snowfall anomaly 171240: - lsfa - Large scale snowfall anomaly 171241: - acfa - Accumulated cloud fraction tendency anomaly 171242: - alwa - Accumulated liquid water tendency anomaly 171243: - fala - Forecast albedo anomaly 171244: - fsra - Forecast surface roughness anomaly 171245: - flsra - Forecast logarithm of surface roughness for heat anomaly 171246: - clwca - Cloud liquid water content anomaly 171247: - ciwca - Cloud ice water content anomaly 171248: - cca - Cloud cover anomaly 171249: - aiwa - Accumulated ice water tendency anomaly 171250: - iaa - Ice age anomaly 171251: - attea - Adiabatic tendency of temperature anomaly 171252: - athea - Adiabatic tendency of humidity anomaly 171253: - atzea - Adiabatic tendency of zonal wind anomaly 171254: - atmwa - Adiabatic tendency of meridional wind anomaly 171255: - _param_171255 - Indicates a missing value 172008: - msror - Time-mean surface runoff rate 172009: - mssror - Time-mean sub-surface runoff rate 172044: - esrate - Time-mean snow evaporation rate - es 172045: - _param_172045 - Time-mean snowmelt rate 172050: - mlspfr - Mean large-scale precipitation fraction - lspf 172142: - mlsprt - Time-mean large-scale precipitation rate - lsp 172143: - cprate - Time-mean convective precipitation rate - cp 172144: - mtsfr - Time-mean total snowfall rate - sf 172145: - bldrate - Boundary layer dissipation 172146: - msshfl - Time-mean surface sensible heat flux - sshf - '146' 172147: - mslhfl - Time-mean surface latent heat flux - slhf - '147' 172149: - msnrf - Mean surface net radiation flux - snr 172153: - mswhr - Time-mean short-wave (solar) heating rate - swhr 172154: - mlwhr - Time-mean long-wave (thermal) heating rate - lwhr 172169: - msdsrf - Time-mean surface downward short-wave (solar) radiation flux - ssrd 172175: - msdtrf - Time-mean surface downward long-wave (thermal) radiation flux - strd 172176: - msnsrf - Time-mean surface net short-wave (solar) radiation flux - ssr 172177: - msntrf - Time-mean surface net long-wave (thermal) radiation flux - str 172178: - mtnsrf - Time-mean top net short-wave (solar) radiation flux - tsr 172179: - mtntrf - Time-mean top net long-wave (thermal) radiation flux - ttr 172180: - ewssra - Time-mean eastward turbulent surface stress - ewss 172181: - nsssra - Time-mean northward turbulent surface stress - nsss 172182: - erate - Time-mean evaporation rate - e 172189: - msdr - Mean sunshine duration rate - sund 172195: - _param_172195 - Longitudinal component of gravity wave stress 172196: - _param_172196 - Meridional component of gravity wave stress 172197: - gwdrate - Gravity wave dissipation 172205: - mrort - Time-mean runoff rate - ro 172208: - _param_172208 - Time-mean top net short-wave (solar) radiation flux, clear sky 172209: - _param_172209 - Time-mean top net long-wave (thermal) radiation flux, clear sky 172210: - _param_172210 - Time-mean surface net short-wave (solar) radiation flux, clear sky 172211: - _param_172211 - Time-mean surface net long-wave (thermal) radiation flux, clear sky 172212: - soira - Time-mean short-wave (solar) insolation rate 172228: - tprate - Time-mean total precipitation rate - tp 172239: - _param_172239 - Time-mean convective snowfall rate 172240: - _param_172240 - Time-mean large-scale snowfall rate 172255: - _param_172255 - Indicates a missing value 173008: - msrora - Mean surface runoff rate anomaly 173009: - mssrora - Mean sub-surface runoff rate anomaly 173044: - _param_173044 - Time-mean snow evaporation anomalous rate of accumulation 173045: - _param_173045 - Time-mean snowmelt anomalous rate of accumulation 173048: - _param_173048 - Magnitude of turbulent surface stress anomaly 173050: - _param_173050 - Large-scale precipitation fraction anomaly 173142: - lspara - Stratiform precipitation (Large-scale precipitation) anomalous rate of accumulation - lspa 173143: - mcpra - Mean convective precipitation rate anomaly - cpa 173144: - sfara - Snowfall (convective + stratiform) anomalous rate of accumulation 173145: - _param_173145 - Boundary layer dissipation anomaly 173146: - sshfara - Surface sensible heat flux anomalous rate of accumulation 173147: - slhfara - Surface latent heat flux anomalous rate of accumulation 173149: - _param_173149 - Surface net radiation anomaly 173153: - _param_173153 - Short-wave heating rate anomaly 173154: - _param_173154 - Long-wave heating rate anomaly 173169: - ssrdara - Surface solar radiation downwards anomalous rate of accumulation - ssrda - ssrd 173175: - strdara - Surface thermal radiation downwards anomalous rate of accumulation - strda 173176: - ssrara - Surface solar radiation anomalous rate of accumulation - ssra - ssr 173177: - strara - Surface thermal radiation anomalous rate of accumulation - stra - str 173178: - tsrara - Top solar radiation anomalous rate of accumulation - tsra - tsr 173179: - ttrara - Top thermal radiation anomalous rate of accumulation - ttra - ttr 173180: - ewssara - East-West surface stress anomalous rate of accumulation 173181: - nsssara - North-South surface stress anomalous rate of accumulation 173182: - evara - Time-mean evaporation anomalous rate of accumulation - ea - e 173189: - sundara - Sunshine duration anomalous rate of accumulation 173195: - _param_173195 - Longitudinal component of gravity wave stress anomaly 173196: - _param_173196 - Meridional component of gravity wave stress anomaly 173197: - _param_173197 - Gravity wave dissipation anomaly 173205: - roara - Runoff anomalous rate of accumulation 173208: - _param_173208 - Top net solar radiation, clear sky anomaly 173209: - _param_173209 - Top net thermal radiation, clear sky anomaly 173210: - _param_173210 - Surface net solar radiation, clear sky anomaly 173211: - _param_173211 - Surface net thermal radiation, clear sky anomaly 173212: - soiara - Solar insolation anomalous rate of accumulation 173228: - tpara - Total precipitation anomalous rate of accumulation 173239: - _param_173239 - Convective snowfall anomaly 173240: - _param_173240 - Large scale snowfall anomaly 173255: - _param_173255 - Indicates a missing value 174006: - _param_174006 - Total soil moisture 174008: - sro - Surface runoff 174010: - sswcsdown - Clear-sky (II) down surface sw flux 174013: - sswcsup - Clear-sky (II) up surface sw flux 174025: - vis15 - Visibility at 1.5m 174031: - _param_174031 - Fraction of sea-ice in sea 174034: - _param_174034 - Open-sea surface temperature 174039: - _param_174039 - Volumetric soil water layer 1 174040: - _param_174040 - Volumetric soil water layer 2 174041: - _param_174041 - Volumetric soil water layer 3 174042: - _param_174042 - Volumetric soil water layer 4 174049: - _param_174049 - 10 metre wind gust in the last 24 hours 174050: - mn15t - Minimum temperature at 1.5m since previous post-processing 174051: - mx15t - Maximum temperature at 1.5m since previous post-processing 174052: - rhum - Relative humidity at 1.5m 174055: - _param_174055 - 1.5m temperature - mean in the last 24 hours 174083: - _param_174083 - Net primary productivity 174085: - _param_174085 - 10m U wind over land 174086: - _param_174086 - 10m V wind over land 174087: - _param_174087 - 1.5m temperature over land 174088: - _param_174088 - 1.5m dewpoint temperature over land 174089: - _param_174089 - Top incoming solar radiation 174090: - _param_174090 - Top outgoing solar radiation 174092: - sialb - Sea ice albedo 174093: - sitemptop - Sea ice surface temperature 174094: - _param_174094 - Mean sea surface temperature 174095: - _param_174095 - 1.5m specific humidity 174096: - 2sh - 2 metre specific humidity 174097: - sisnthick - Sea ice snow thickness 174098: - sithick - Sea-ice thickness 174099: - _param_174099 - Liquid water potential temperature 174110: - _param_174110 - Ocean ice concentration 174111: - _param_174111 - Ocean mean ice depth 174112: - siue - Sea ice velocity along x 174113: - sivn - Sea ice velocity along y 174116: - swrsurf - Short wave radiation flux at surface 174117: - swrtop - Short wave radiation flux at top of atmosphere 174137: - tcwvap - Total column water vapour 174139: - _param_174139 - Soil temperature layer 1 174142: - lsrrate - Large scale rainfall rate 174143: - crfrate - Convective rainfall rate 174164: - _param_174164 - Average potential temperature in upper 293.4m 174167: - _param_174167 - 1.5m temperature 174168: - _param_174168 - 1.5m dewpoint temperature 174170: - _param_174170 - Soil temperature layer 2 174175: - _param_174175 - Average salinity in upper 293.4m 174183: - _param_174183 - Soil temperature layer 3 174186: - vlca - Very low cloud amount 174201: - _param_174201 - 1.5m temperature - maximum in the last 24 hours 174202: - _param_174202 - 1.5m temperature - minimum in the last 24 hours 174236: - _param_174236 - Soil temperature layer 4 174239: - csfrate - Convective snowfall rate 174240: - lsfrate - Large scale snowfall rate 174248: - tccro - Total cloud amount - random overlap 174249: - tcclwr - Total cloud amount in lw radiation 174255: - _param_174255 - Indicates a missing value 175006: - _param_175006 - Total soil moisture 175031: - _param_175031 - Fraction of sea-ice in sea 175034: - _param_175034 - Open-sea surface temperature 175039: - _param_175039 - Volumetric soil water layer 1 175040: - _param_175040 - Volumetric soil water layer 2 175041: - _param_175041 - Volumetric soil water layer 3 175042: - _param_175042 - Volumetric soil water layer 4 175049: - _param_175049 - 10m wind gust in the last 24 hours 175055: - _param_175055 - 1.5m temperature - mean in the last 24 hours 175083: - _param_175083 - Net primary productivity 175085: - _param_175085 - 10m U wind over land 175086: - _param_175086 - 10m V wind over land 175087: - _param_175087 - 1.5m temperature over land 175088: - _param_175088 - 1.5m dewpoint temperature over land 175089: - _param_175089 - Top incoming solar radiation 175090: - _param_175090 - Top outgoing solar radiation 175110: - _param_175110 - Ocean ice concentration 175111: - _param_175111 - Ocean mean ice depth 175139: - _param_175139 - Soil temperature layer 1 175164: - _param_175164 - Average potential temperature in upper 293.4m 175167: - _param_175167 - 1.5m temperature 175168: - _param_175168 - 1.5m dewpoint temperature 175170: - _param_175170 - Soil temperature layer 2 175175: - _param_175175 - Average salinity in upper 293.4m 175183: - _param_175183 - Soil temperature layer 3 175201: - _param_175201 - 1.5m temperature - maximum in the last 24 hours 175202: - _param_175202 - 1.5m temperature - minimum in the last 24 hours 175236: - _param_175236 - Soil temperature layer 4 175255: - _param_175255 - Indicates a missing value 180149: - tsw - Total soil wetness 180176: - ssr - Surface net solar radiation 180177: - str - Surface net thermal radiation 180178: - tsr - Top net solar radiation 180179: - ttr - Top net thermal radiation 190141: - sdsien - Snow depth 190170: - cap - Field capacity 190171: - wiltsien - Wilting point 190173: - sr - Roughness length 190229: - tsm - Total soil moisture 200001: - strfdiff - Stream function difference 200002: - vpotdiff - Velocity potential difference 200003: - ptdiff - Potential temperature difference 200004: - eqptdiff - Equivalent potential temperature difference 200005: - septdiff - Saturated equivalent potential temperature difference 200011: - udvwdiff - U component of divergent wind difference 200012: - vdvwdiff - V component of divergent wind difference 200013: - urtwdiff - U component of rotational wind difference 200014: - vrtwdiff - V component of rotational wind difference 200021: - uctpdiff - Unbalanced component of temperature difference 200022: - uclndiff - Unbalanced component of logarithm of surface pressure difference 200023: - ucdvdiff - Unbalanced component of divergence difference 200024: - _param_200024 - Reserved for future unbalanced components 200025: - _param_200025 - Reserved for future unbalanced components 200026: - cldiff - Lake cover difference 200027: - cvldiff - Low vegetation cover difference 200028: - cvhdiff - High vegetation cover difference 200029: - tvldiff - Type of low vegetation difference 200030: - tvhdiff - Type of high vegetation difference 200031: - sicdiff - Sea-ice cover difference 200032: - asndiff - Snow albedo difference 200033: - rsndiff - Snow density difference 200034: - sstdiff - Sea surface temperature difference 200035: - istl1diff - Ice surface temperature layer 1 difference 200036: - istl2diff - Ice surface temperature layer 2 difference 200037: - istl3diff - Ice surface temperature layer 3 difference 200038: - istl4diff - Ice surface temperature layer 4 difference 200039: - swvl1diff - Volumetric soil water layer 1 difference 200040: - swvl2diff - Volumetric soil water layer 2 difference 200041: - swvl3diff - Volumetric soil water layer 3 difference 200042: - swvl4diff - Volumetric soil water layer 4 difference 200043: - sltdiff - Soil type difference 200044: - esdiff - Snow evaporation difference 200045: - smltdiff - Snowmelt difference 200046: - sdurdiff - Solar duration difference 200047: - dsrpdiff - Direct solar radiation difference 200048: - magssdiff - Magnitude of turbulent surface stress difference 200049: - 10fgdiff - 10 metre wind gust difference 200050: - lspfdiff - Large-scale precipitation fraction difference 200051: - mx2t24diff - Maximum 2 metre temperature difference 200052: - mn2t24diff - Minimum 2 metre temperature difference 200053: - montdiff - Montgomery potential difference 200054: - presdiff - Pressure difference 200055: - mean2t24diff - Mean 2 metre temperature in the last 24 hours difference 200056: - mn2d24diff - Mean 2 metre dewpoint temperature in the last 24 hours difference 200057: - uvbdiff - Downward UV radiation at the surface difference 200058: - pardiff - Photosynthetically active radiation at the surface difference 200059: - capediff - Convective available potential energy difference 200060: - pvdiff - Potential vorticity difference 200061: - tpodiff - Total precipitation from observations difference 200062: - obctdiff - Observation count difference 200063: - _param_200063 - Start time for skin temperature difference 200064: - _param_200064 - Finish time for skin temperature difference 200065: - _param_200065 - Skin temperature difference 200066: - _param_200066 - Leaf area index, low vegetation 200067: - _param_200067 - Leaf area index, high vegetation 200070: - _param_200070 - Biome cover, low vegetation 200071: - _param_200071 - Biome cover, high vegetation 200078: - _param_200078 - Total column liquid water 200079: - _param_200079 - Total column ice water 200080: - _param_200080 - Experimental product 200081: - _param_200081 - Experimental product 200082: - _param_200082 - Experimental product 200083: - _param_200083 - Experimental product 200084: - _param_200084 - Experimental product 200085: - _param_200085 - Experimental product 200086: - _param_200086 - Experimental product 200087: - _param_200087 - Experimental product 200088: - _param_200088 - Experimental product 200089: - _param_200089 - Experimental product 200090: - _param_200090 - Experimental product 200091: - _param_200091 - Experimental product 200092: - _param_200092 - Experimental product 200093: - _param_200093 - Experimental product 200094: - _param_200094 - Experimental product 200095: - _param_200095 - Experimental product 200096: - _param_200096 - Experimental product 200097: - _param_200097 - Experimental product 200098: - _param_200098 - Experimental product 200099: - _param_200099 - Experimental product 200100: - _param_200100 - Experimental product 200101: - _param_200101 - Experimental product 200102: - _param_200102 - Experimental product 200103: - _param_200103 - Experimental product 200104: - _param_200104 - Experimental product 200105: - _param_200105 - Experimental product 200106: - _param_200106 - Experimental product 200107: - _param_200107 - Experimental product 200108: - _param_200108 - Experimental product 200109: - _param_200109 - Experimental product 200110: - _param_200110 - Experimental product 200111: - _param_200111 - Experimental product 200112: - _param_200112 - Experimental product 200113: - _param_200113 - Experimental product 200114: - _param_200114 - Experimental product 200115: - _param_200115 - Experimental product 200116: - _param_200116 - Experimental product 200117: - _param_200117 - Experimental product 200118: - _param_200118 - Experimental product 200119: - _param_200119 - Experimental product 200120: - _param_200120 - Experimental product 200121: - mx2t6diff - Maximum temperature at 2 metres difference 200122: - mn2t6diff - Minimum temperature at 2 metres difference 200123: - 10fg6diff - 10 metre wind gust in the last 6 hours difference 200125: - _param_200125 - Vertically integrated total energy 200126: - _param_200126 - Generic parameter for sensitive area prediction 200127: - atdiff - Atmospheric tide difference 200128: - bvdiff - Budget values difference 200129: - zdiff - Geopotential difference 200130: - tdiff - Temperature difference 200131: - udiff - U component of wind difference 200132: - vdiff - V component of wind difference 200133: - qdiff - Specific humidity difference 200134: - spdiff - Surface pressure difference 200135: - wdiff - Vertical velocity (pressure) difference 200136: - tcwdiff - Total column water difference 200137: - tcwvdiff - Total column water vapour difference 200138: - vodiff - Vorticity (relative) difference 200139: - stl1diff - Soil temperature level 1 difference 200140: - swl1diff - Soil wetness level 1 difference 200141: - sddiff - Snow depth difference 200142: - lspdiff - Stratiform precipitation (Large-scale precipitation) difference 200143: - cpdiff - Convective precipitation difference 200144: - sfdiff - Snowfall (convective + stratiform) difference 200145: - blddiff - Boundary layer dissipation difference 200146: - sshfdiff - Surface sensible heat flux difference 200147: - slhfdiff - Surface latent heat flux difference 200148: - chnkdiff - Charnock difference 200149: - snrdiff - Surface net radiation difference 200150: - tnrdiff - Top net radiation difference 200151: - msldiff - Mean sea level pressure difference 200152: - lnspdiff - Logarithm of surface pressure difference 200153: - swhrdiff - Short-wave heating rate difference 200154: - lwhrdiff - Long-wave heating rate difference 200155: - ddiff - Divergence difference 200156: - ghdiff - Height difference 200157: - rdiff - Relative humidity difference 200158: - tspdiff - Tendency of surface pressure difference 200159: - blhdiff - Boundary layer height difference 200160: - sdordiff - Standard deviation of orography difference 200161: - isordiff - Anisotropy of sub-gridscale orography difference 200162: - anordiff - Angle of sub-gridscale orography difference 200163: - slordiff - Slope of sub-gridscale orography difference 200164: - tccdiff - Total cloud cover difference 200165: - 10udiff - 10 metre U wind component difference 200166: - 10vdiff - 10 metre V wind component difference 200167: - 2tdiff - 2 metre temperature difference 200168: - 2ddiff - 2 metre dewpoint temperature difference 200169: - ssrddiff - Surface solar radiation downwards difference 200170: - stl2diff - Soil temperature level 2 difference 200171: - swl2diff - Soil wetness level 2 difference 200172: - lsmdiff - Land-sea mask difference 200173: - srdiff - Surface roughness difference 200174: - aldiff - Albedo difference 200175: - strddiff - Surface thermal radiation downwards difference 200176: - ssrdiff - Surface net solar radiation difference 200177: - strdiff - Surface net thermal radiation difference 200178: - tsrdiff - Top net solar radiation difference 200179: - ttrdiff - Top net thermal radiation difference 200180: - ewssdiff - East-West surface stress difference 200181: - nsssdiff - North-South surface stress difference 200182: - ediff - Evaporation difference 200183: - stl3diff - Soil temperature level 3 difference 200184: - swl3diff - Soil wetness level 3 difference 200185: - cccdiff - Convective cloud cover difference 200186: - lccdiff - Low cloud cover difference 200187: - mccdiff - Medium cloud cover difference 200188: - hccdiff - High cloud cover difference 200189: - sunddiff - Sunshine duration difference 200190: - ewovdiff - East-West component of sub-gridscale orographic variance difference 200191: - nsovdiff - North-South component of sub-gridscale orographic variance difference 200192: - nwovdiff - North-West/South-East component of sub-gridscale orographic variance difference 200193: - neovdiff - North-East/South-West component of sub-gridscale orographic variance difference 200194: - btmpdiff - Brightness temperature difference 200195: - lgwsdiff - Longitudinal component of gravity wave stress difference 200196: - mgwsdiff - Meridional component of gravity wave stress difference 200197: - gwddiff - Gravity wave dissipation difference 200198: - srcdiff - Skin reservoir content difference 200199: - vegdiff - Vegetation fraction difference 200200: - vsodiff - Variance of sub-gridscale orography difference 200201: - mx2tdiff - Maximum temperature at 2 metres since previous post-processing difference 200202: - mn2tdiff - Minimum temperature at 2 metres since previous post-processing difference 200203: - o3diff - Ozone mass mixing ratio difference 200204: - pawdiff - Precipitation analysis weights difference 200205: - rodiff - Runoff difference 200206: - tco3diff - Total column ozone difference 200207: - 10sidiff - 10 metre wind speed difference 200208: - tsrcdiff - Top net solar radiation, clear sky difference 200209: - ttrcdiff - Top net thermal radiation, clear sky difference 200210: - ssrcdiff - Surface net solar radiation, clear sky difference 200211: - strcdiff - Surface net thermal radiation, clear sky difference 200212: - tisrdiff - TOA incident solar radiation difference 200214: - dhrdiff - Diabatic heating by radiation difference 200215: - dhvddiff - Diabatic heating by vertical diffusion difference 200216: - dhccdiff - Diabatic heating by cumulus convection difference 200217: - dhlcdiff - Diabatic heating large-scale condensation difference 200218: - vdzwdiff - Vertical diffusion of zonal wind difference 200219: - vdmwdiff - Vertical diffusion of meridional wind difference 200220: - ewgddiff - East-West gravity wave drag tendency difference 200221: - nsgddiff - North-South gravity wave drag tendency difference 200222: - ctzwdiff - Convective tendency of zonal wind difference 200223: - ctmwdiff - Convective tendency of meridional wind difference 200224: - vdhdiff - Vertical diffusion of humidity difference 200225: - htccdiff - Humidity tendency by cumulus convection difference 200226: - htlcdiff - Humidity tendency by large-scale condensation difference 200227: - crnhdiff - Change from removal of negative humidity difference 200228: - tpdiff - Total precipitation difference 200229: - iewsdiff - Instantaneous X surface stress difference 200230: - inssdiff - Instantaneous Y surface stress difference 200231: - ishfdiff - Instantaneous surface heat flux difference 200232: - iediff - Instantaneous moisture flux difference 200233: - asqdiff - Apparent surface humidity difference 200234: - lsrhdiff - Logarithm of surface roughness length for heat difference 200235: - sktdiff - Skin temperature difference 200236: - stl4diff - Soil temperature level 4 difference 200237: - swl4diff - Soil wetness level 4 difference 200238: - tsndiff - Temperature of snow layer difference 200239: - csfdiff - Convective snowfall difference 200240: - lsfdiff - Large scale snowfall difference 200241: - acfdiff - Accumulated cloud fraction tendency difference 200242: - alwdiff - Accumulated liquid water tendency difference 200243: - faldiff - Forecast albedo difference 200244: - fsrdiff - Forecast surface roughness difference 200245: - flsrdiff - Forecast logarithm of surface roughness for heat difference 200246: - clwcdiff - Specific cloud liquid water content difference 200247: - ciwcdiff - Specific cloud ice water content difference 200248: - ccdiff - Cloud cover difference 200249: - aiwdiff - Accumulated ice water tendency difference 200250: - icediff - Ice age difference 200251: - attediff - Adiabatic tendency of temperature difference 200252: - athediff - Adiabatic tendency of humidity difference 200253: - atzediff - Adiabatic tendency of zonal wind difference 200254: - atmwdiff - Adiabatic tendency of meridional wind difference 200255: - _param_200255 - Indicates a missing value 201001: - _param_201001 - downward shortwave radiant flux density 201002: - _param_201002 - upward shortwave radiant flux density 201003: - _param_201003 - downward longwave radiant flux density 201004: - _param_201004 - upward longwave radiant flux density 201005: - apab_s - downwd photosynthetic active radiant flux density 201006: - _param_201006 - net shortwave flux 201007: - _param_201007 - net longwave flux 201008: - _param_201008 - total net radiative flux density 201009: - _param_201009 - downw shortw radiant flux density, cloudfree part 201010: - _param_201010 - upw shortw radiant flux density, cloudy part 201011: - _param_201011 - downw longw radiant flux density, cloudfree part 201012: - _param_201012 - upw longw radiant flux density, cloudy part 201013: - sohr_rad - shortwave radiative heating rate 201014: - thhr_rad - longwave radiative heating rate 201015: - _param_201015 - total radiative heating rate 201016: - _param_201016 - soil heat flux, surface 201017: - _param_201017 - soil heat flux, bottom of layer 201029: - clc - fractional cloud cover 201030: - _param_201030 - cloud cover, grid scale 201031: - qc - specific cloud water content 201032: - _param_201032 - cloud water content, grid scale, vert integrated 201033: - qi - specific cloud ice content, grid scale 201034: - _param_201034 - cloud ice content, grid scale, vert integrated 201035: - _param_201035 - specific rainwater content, grid scale 201036: - _param_201036 - specific snow content, grid scale 201037: - _param_201037 - specific rainwater content, gs, vert. integrated 201038: - _param_201038 - specific snow content, gs, vert. integrated 201041: - twater - total column water 201042: - _param_201042 - vert. integral of divergence of tot. water content 201050: - ch_cm_cl - cloud covers CH_CM_CL (000...888) 201051: - _param_201051 - cloud cover CH (0..8) 201052: - _param_201052 - cloud cover CM (0..8) 201053: - _param_201053 - cloud cover CL (0..8) 201054: - _param_201054 - total cloud cover (0..8) 201055: - _param_201055 - fog (0..8) 201056: - _param_201056 - fog 201060: - _param_201060 - cloud cover, convective cirrus 201061: - _param_201061 - specific cloud water content, convective clouds 201062: - _param_201062 - cloud water content, conv clouds, vert integrated 201063: - _param_201063 - specific cloud ice content, convective clouds 201064: - _param_201064 - cloud ice content, conv clouds, vert integrated 201065: - _param_201065 - convective mass flux 201066: - _param_201066 - Updraft velocity, convection 201067: - _param_201067 - entrainment parameter, convection 201068: - hbas_con - cloud base, convective clouds (above msl) 201069: - htop_con - cloud top, convective clouds (above msl) 201070: - _param_201070 - convective layers (00...77) (BKE) 201071: - _param_201071 - KO-index 201072: - bas_con - convection base index 201073: - top_con - convection top index 201074: - dt_con - convective temperature tendency 201075: - dqv_con - convective tendency of specific humidity 201076: - _param_201076 - convective tendency of total heat 201077: - _param_201077 - convective tendency of total water 201078: - du_con - convective momentum tendency (X-component) 201079: - dv_con - convective momentum tendency (Y-component) 201080: - _param_201080 - convective vorticity tendency 201081: - _param_201081 - convective divergence tendency 201082: - htop_dc - top of dry convection (above msl) 201083: - _param_201083 - dry convection top index 201084: - hzerocl - height of 0 degree Celsius isotherm above msl 201085: - snowlmt - height of snow-fall limit 201099: - qrs_gsp - spec. content of precip. particles 201100: - prr_gsp - surface precipitation rate, rain, grid scale 201101: - prs_gsp - surface precipitation rate, snow, grid scale 201102: - rain_gsp - surface precipitation amount, rain, grid scale 201111: - prr_con - surface precipitation rate, rain, convective 201112: - prs_con - surface precipitation rate, snow, convective 201113: - rain_con - surface precipitation amount, rain, convective 201150: - _param_201150 - coefficient of horizontal diffusion 201187: - vmax_10m - Maximum wind velocity 201200: - w_i - water content of interception store 201203: - t_snow - snow temperature 201215: - t_ice - ice surface temperature 201241: - cape_con - convective available potential energy 201255: - _param_201255 - Indicates a missing value 210001: - aermr01 - Sea Salt Aerosol (0.03 - 0.5 um) Mixing Ratio 210002: - aermr02 - Sea Salt Aerosol (0.5 - 5 um) Mixing Ratio 210003: - aermr03 - Sea Salt Aerosol (5 - 20 um) Mixing Ratio 210004: - aermr04 - Dust Aerosol (0.03 - 0.55 um) Mixing Ratio 210005: - aermr05 - Dust Aerosol (0.55 - 0.9 um) Mixing Ratio 210006: - aermr06 - Dust Aerosol (0.9 - 20 um) Mixing Ratio 210007: - aermr07 - Hydrophilic Organic Matter Aerosol Mixing Ratio 210008: - aermr08 - Hydrophobic Organic Matter Aerosol Mixing Ratio 210009: - aermr09 - Hydrophilic Black Carbon Aerosol Mixing Ratio 210010: - aermr10 - Hydrophobic Black Carbon Aerosol Mixing Ratio 210011: - aermr11 - Sulphate Aerosol Mixing Ratio 210012: - aermr12 - SO2 precursor mixing ratio 210013: - aermr13 - Volcanic ash aerosol mixing ratio 210014: - aermr14 - Volcanic sulphate aerosol mixing ratio 210015: - aermr15 - Volcanic SO2 precursor mixing ratio 210016: - aergn01 - Aerosol type 1 source/gain accumulated 210017: - aergn02 - Aerosol type 2 source/gain accumulated 210018: - aergn03 - Aerosol type 3 source/gain accumulated 210019: - aergn04 - Aerosol type 4 source/gain accumulated 210020: - aergn05 - Aerosol type 5 source/gain accumulated 210021: - aergn06 - Aerosol type 6 source/gain accumulated 210022: - aergn07 - Aerosol type 7 source/gain accumulated 210023: - aergn08 - Aerosol type 8 source/gain accumulated 210024: - aergn09 - Aerosol type 9 source/gain accumulated 210025: - aergn10 - Aerosol type 10 source/gain accumulated 210026: - aergn11 - Aerosol type 11 source/gain accumulated 210027: - aergn12 - Aerosol type 12 source/gain accumulated 210028: - aerpr03 - SO4 aerosol precursor mass mixing ratio 210029: - aerwv01 - Water vapour mixing ratio for hydrophilic aerosols in mode 1 210030: - aerwv02 - Water vapour mixing ratio for hydrophilic aerosols in mode 2 210031: - aerls01 - Aerosol type 1 sink/loss accumulated 210032: - aerls02 - Aerosol type 2 sink/loss accumulated 210033: - aerls03 - Aerosol type 3 sink/loss accumulated 210034: - aerls04 - Aerosol type 4 sink/loss accumulated 210035: - aerls05 - Aerosol type 5 sink/loss accumulated 210036: - aerls06 - Aerosol type 6 sink/loss accumulated 210037: - aerls07 - Aerosol type 7 sink/loss accumulated 210038: - aerls08 - Aerosol type 8 sink/loss accumulated 210039: - aerls09 - Aerosol type 9 sink/loss accumulated 210040: - aerls10 - Aerosol type 10 sink/loss accumulated 210041: - aerls11 - Aerosol type 11 sink/loss accumulated 210042: - aerls12 - Aerosol type 12 sink/loss accumulated 210043: - emdms - DMS surface emission 210044: - aerwv03 - Water vapour mixing ratio for hydrophilic aerosols in mode 3 210045: - aerwv04 - Water vapour mixing ratio for hydrophilic aerosols in mode 4 210046: - aerpr - Aerosol precursor mixing ratio 210047: - aersm - Aerosol small mode mixing ratio 210048: - aerlg - Aerosol large mode mixing ratio 210049: - aodpr - Aerosol precursor optical depth 210050: - aodsm - Aerosol small mode optical depth 210051: - aodlg - Aerosol large mode optical depth 210052: - aerdep - Dust emission potential 210053: - aerlts - Lifting threshold speed 210054: - aerscc - Soil clay content 210055: - _param_210055 - Experimental product 210056: - _param_210056 - Experimental product 210057: - ocnuc - Mixing ration of organic carbon aerosol, nucleation mode 210058: - monot - Monoterpene precursor mixing ratio 210059: - soapr - Secondary organic precursor mixing ratio 210060: - injh - Injection height (from IS4FIRES) 210061: - co2 - Carbon dioxide mass mixing ratio 210062: - ch4 - Methane 210063: - n2o - Nitrous oxide 210064: - tcco2 - CO2 column-mean molar fraction 210065: - tcch4 - CH4 column-mean molar fraction 210066: - tcn2o - Total column Nitrous oxide 210067: - co2of - Ocean flux of Carbon Dioxide 210068: - co2nbf - Natural biosphere flux of Carbon Dioxide 210069: - co2apf - Anthropogenic emissions of Carbon Dioxide 210070: - ch4f - Methane Surface Fluxes 210071: - kch4 - Methane loss rate due to radical hydroxyl (OH) 210072: - pm1 - Particulate matter d <= 1 um 210073: - pm2p5 - Particulate matter d <= 2.5 um 210074: - pm10 - Particulate matter d <= 10 um 210079: - vafire - Wildfire viewing angle of observation 210080: - co2fire - Wildfire flux of Carbon Dioxide 210081: - cofire - Wildfire flux of Carbon Monoxide 210082: - ch4fire - Wildfire flux of Methane 210083: - nmhcfire - Wildfire flux of Non-Methane Hydro-Carbons 210084: - h2fire - Wildfire flux of Hydrogen 210085: - noxfire - Wildfire flux of Nitrogen Oxides NOx 210086: - n2ofire - Wildfire flux of Nitrous Oxide 210087: - pm2p5fire - Wildfire flux of Particulate Matter PM2.5 210088: - tpmfire - Wildfire flux of Total Particulate Matter 210089: - tcfire - Wildfire flux of Total Carbon in Aerosols 210090: - ocfire - Wildfire flux of Organic Carbon 210091: - bcfire - Wildfire flux of Black Carbon 210092: - cfire - Wildfire overall flux of burnt Carbon 210093: - c4ffire - Wildfire fraction of C4 plants 210094: - vegfire - Wildfire vegetation map index 210095: - ccfire - Wildfire Combustion Completeness 210096: - flfire - 'Wildfire Fuel Load: Carbon per unit area' 210097: - offire - Wildfire fraction of area observed 210098: - nofrp - Number of positive FRP pixels per grid cell 210099: - frpfire - Wildfire radiative power 210100: - crfire - Wildfire combustion rate 210101: - maxfrpfire - Wildfire radiative power maximum 210102: - so2fire - Wildfire flux of Sulfur Dioxide 210103: - ch3ohfire - Wildfire Flux of Methanol (CH3OH) 210104: - c2h5ohfire - Wildfire Flux of Ethanol (C2H5OH) 210105: - c3h8fire - Wildfire Flux of Propane (C3H8) 210106: - c2h4fire - Wildfire Flux of Ethene (C2H4) 210107: - c3h6fire - Wildfire Flux of Propene (C3H6) 210108: - c5h8fire - Wildfire Flux of Isoprene (C5H8) 210109: - terpenesfire - Wildfire Flux of Terpenes (C5H8)n 210110: - toluenefire - Wildfire Flux of Toluene_lump (C7H8+ C6H6 + C8H10) 210111: - hialkenesfire - Wildfire Flux of Higher Alkenes (CnH2n, C>=4) 210112: - hialkanesfire - Wildfire Flux of Higher Alkanes (CnH2n+2, C>=4) 210113: - ch2ofire - Wildfire Flux of Formaldehyde (CH2O) 210114: - c2h4ofire - Wildfire Flux of Acetaldehyde (C2H4O) 210115: - c3h6ofire - Wildfire Flux of Acetone (C3H6O) 210116: - nh3fire - Wildfire Flux of Ammonia (NH3) 210117: - c2h6sfire - Wildfire Flux of Dimethyl Sulfide (DMS) (C2H6S) 210118: - c2h6fire - Wildfire Flux of Ethane (C2H6) 210119: - mami - Mean height of maximum injection 210120: - apt - Plume top height above surface 210121: - no2 - Nitrogen dioxide mass mixing ratio 210122: - so2 - Sulphur dioxide mass mixing ratio 210123: - co - Carbon monoxide mass mixing ratio 210124: - hcho - Formaldehyde 210125: - tcno2 - Total column Nitrogen dioxide 210126: - tcso2 - Total column Sulphur dioxide 210127: - tcco - Total column Carbon monoxide 210128: - tchcho - Total column Formaldehyde 210129: - nox - Nitrogen Oxides 210130: - tcnox - Total Column Nitrogen Oxides 210131: - grg1 - Reactive tracer 1 mass mixing ratio 210132: - tcgrg1 - Total column GRG tracer 1 210133: - grg2 - Reactive tracer 2 mass mixing ratio 210134: - tcgrg2 - Total column GRG tracer 2 210135: - grg3 - Reactive tracer 3 mass mixing ratio 210136: - tcgrg3 - Total column GRG tracer 3 210137: - grg4 - Reactive tracer 4 mass mixing ratio 210138: - tcgrg4 - Total column GRG tracer 4 210139: - grg5 - Reactive tracer 5 mass mixing ratio 210140: - tcgrg5 - Total column GRG tracer 5 210141: - grg6 - Reactive tracer 6 mass mixing ratio 210142: - tcgrg6 - Total column GRG tracer 6 210143: - grg7 - Reactive tracer 7 mass mixing ratio 210144: - tcgrg7 - Total column GRG tracer 7 210145: - grg8 - Reactive tracer 8 mass mixing ratio 210146: - tcgrg8 - Total column GRG tracer 8 210147: - grg9 - Reactive tracer 9 mass mixing ratio 210148: - tcgrg9 - Total column GRG tracer 9 210149: - grg10 - Reactive tracer 10 mass mixing ratio 210150: - tcgrg10 - Total column GRG tracer 10 210151: - sfnox - Surface flux Nitrogen oxides 210152: - sfno2 - Surface flux Nitrogen dioxide 210153: - sfso2 - Surface flux Sulphur dioxide 210154: - sfco2 - Surface flux Carbon monoxide 210155: - sfhcho - Surface flux Formaldehyde 210156: - sfgo3 - Surface flux GEMS Ozone 210157: - sfgr1 - Surface flux reactive tracer 1 210158: - sfgr2 - Surface flux reactive tracer 2 210159: - sfgr3 - Surface flux reactive tracer 3 210160: - sfgr4 - Surface flux reactive tracer 4 210161: - sfgr5 - Surface flux reactive tracer 5 210162: - sfgr6 - Surface flux reactive tracer 6 210163: - sfgr7 - Surface flux reactive tracer 7 210164: - sfgr8 - Surface flux reactive tracer 8 210165: - sfgr9 - Surface flux reactive tracer 9 210166: - sfgr10 - Surface flux reactive tracer 10 210167: - frpdayfire - Wildfire day-time radiative power 210169: - frpngtfire - Wildfire night-time radiative power 210170: - vso2 - Volcanic sulfur dioxide mass mixing ratio 210177: - frpdayivar - Wildfire day-time inverse variance of radiative power 210179: - frpngtivar - Wildfire night-time inverse variance of radiative power 210181: - ra - Radon 210182: - sf6 - Sulphur Hexafluoride 210183: - tcra - Total column Radon 210184: - tcsf6 - Total column Sulphur Hexafluoride 210185: - sf6apf - Anthropogenic Emissions of Sulphur Hexafluoride 210186: - aluvpi - UV visible albedo for direct radiation, isotropic component (climatological) 210187: - aluvpv - UV visible albedo for direct radiation, volumetric component (climatological) 210188: - aluvpg - UV visible albedo for direct radiation, geometric component (climatological) 210189: - alnipi - Near IR albedo for direct radiation, isotropic component (climatological) 210190: - alnipv - Near IR albedo for direct radiation, volumetric component (climatological) 210191: - alnipg - Near IR albedo for direct radiation, geometric component (climatological) 210192: - aluvdi - UV visible albedo for diffuse radiation, isotropic component (climatological) 210193: - aluvdv - UV visible albedo for diffuse radiation, volumetric component (climatological) 210194: - aluvdg - UV visible albedo for diffuse radiation, geometric component (climatological) 210195: - alnidi - Near IR albedo for diffuse radiation, isotropic component (climatological) 210196: - alnidv - Near IR albedo for diffuse radiation, volumetric component (climatological) 210197: - alnidg - Near IR albedo for diffuse radiation, geometric component (climatological) 210198: - aluvd_p - UV visible albedo for diffuse radiation (climatological) 210199: - aluvp_p - UV visible albedo for direct radiation (climatological) 210200: - aluvpg_p - UV visible albedo for direct radiation, geometric component (climatological) 210201: - aluvpi_p - UV visible albedo for direct radiation, isotropic component (climatological) 210202: - aluvpv_p - UV visible albedo for direct radiation, volumetric component (climatological) 210203: - go3 - Ozone mass mixing ratio (full chemistry scheme) 210206: - gtco3 - GEMS Total column ozone 210207: - aod550 - Total Aerosol Optical Depth at 550nm 210208: - ssaod550 - Sea Salt Aerosol Optical Depth at 550nm 210209: - duaod550 - Dust Aerosol Optical Depth at 550nm 210210: - omaod550 - Organic Matter Aerosol Optical Depth at 550nm 210211: - bcaod550 - Black Carbon Aerosol Optical Depth at 550nm 210212: - suaod550 - Sulphate Aerosol Optical Depth at 550nm 210213: - aod469 - Total Aerosol Optical Depth at 469nm 210214: - aod670 - Total Aerosol Optical Depth at 670nm 210215: - aod865 - Total Aerosol Optical Depth at 865nm 210216: - aod1240 - Total Aerosol Optical Depth at 1240nm 210217: - aod340 - Total aerosol optical depth at 340 nm 210218: - aod355 - Total aerosol optical depth at 355 nm 210219: - aod380 - Total aerosol optical depth at 380 nm 210220: - aod400 - Total aerosol optical depth at 400 nm 210221: - aod440 - Total aerosol optical depth at 440 nm 210222: - aod500 - Total aerosol optical depth at 500 nm 210223: - aod532 - Total aerosol optical depth at 532 nm 210224: - aod645 - Total aerosol optical depth at 645 nm 210225: - aod800 - Total aerosol optical depth at 800 nm 210226: - aod858 - Total aerosol optical depth at 858 nm 210227: - aod1020 - Total aerosol optical depth at 1020 nm 210228: - aod1064 - Total aerosol optical depth at 1064 nm 210229: - aod1640 - Total aerosol optical depth at 1640 nm 210230: - aod2130 - Total aerosol optical depth at 2130 nm 210231: - c7h8fire - Wildfire Flux of Toluene (C7H8) 210232: - c6h6fire - Wildfire Flux of Benzene (C6H6) 210233: - c8h10fire - Wildfire Flux of Xylene (C8H10) 210234: - c4h8fire - Wildfire Flux of Butenes (C4H8) 210235: - c5h10fire - Wildfire Flux of Pentenes (C5H10) 210236: - c6h12fire - Wildfire Flux of Hexene (C6H12) 210237: - c8h16fire - Wildfire Flux of Octene (C8H16) 210238: - c4h10fire - Wildfire Flux of Butanes (C4H10) 210239: - c5h12fire - Wildfire Flux of Pentanes (C5H12) 210240: - c6h14fire - Wildfire Flux of Hexanes (C6H14) 210241: - c7h16fire - Wildfire Flux of Heptane (C7H16) 210242: - apb - Plume bottom height above surface 210243: - vsuaod550 - Volcanic sulphate aerosol optical depth at 550 nm 210244: - vashaod550 - Volcanic ash optical depth at 550 nm 210245: - taedec550 - Profile of total aerosol dry extinction coefficient 210246: - taedab550 - Profile of total aerosol dry absorption coefficient 210247: - aermr16 - Nitrate fine mode aerosol mass mixing ratio 210248: - aermr17 - Nitrate coarse mode aerosol mass mixing ratio 210249: - aermr18 - Ammonium aerosol mass mixing ratio 210250: - niaod550 - Nitrate aerosol optical depth at 550 nm 210251: - amaod550 - Ammonium aerosol optical depth at 550 nm 210252: - aermr19 - Biogenic secondary organic aerosol mass mixing ratio 210253: - aermr20 - Anthropogenic secondary organic aerosol mass mixing ratio 210260: - alnid_p - Near IR albedo for diffuse radiation (climatological) 210261: - alnip_p - Near IR albedo for direct radiation (climatological) 210262: - alnipg_p - Near IR albedo for direct radiation, geometric component (climatological) 210263: - alnipi_p - Near IR albedo for direct radiation, isotropic component (climatological) 210264: - alnipv_p - Near IR albedo for direct radiation, volumetric component (climatological) 211001: - aermr01diff - Sea Salt Aerosol (0.03 - 0.5 um) Mixing Ratio 211002: - aermr02diff - Sea Salt Aerosol (0.5 - 5 um) Mixing Ratio 211003: - aermr03diff - Sea Salt Aerosol (5 - 20 um) Mixing Ratio 211004: - aermr04diff - Dust Aerosol (0.03 - 0.55 um) Mixing Ratio 211005: - aermr05diff - Dust Aerosol (0.55 - 0.9 um) Mixing Ratio 211006: - aermr06diff - Dust Aerosol (0.9 - 20 um) Mixing Ratio 211007: - aermr07diff - Hydrophilic Organic Matter Aerosol Mixing Ratio 211008: - aermr08diff - Hydrophobic Organic Matter Aerosol Mixing Ratio 211009: - aermr09diff - Hydrophilic Black Carbon Aerosol Mixing Ratio 211010: - aermr10diff - Hydrophobic Black Carbon Aerosol Mixing Ratio 211011: - aermr11diff - Sulphate Aerosol Mixing Ratio 211012: - aermr12diff - Aerosol type 12 mixing ratio 211013: - aermr13diff - Aerosol type 13 mass mixing ratio 211014: - aermr14diff - Aerosol type 14 mass mixing ratio 211015: - aermr15diff - Aerosol type 15 mass mixing ratio 211016: - aergn01diff - Aerosol type 1 source/gain accumulated 211017: - aergn02diff - Aerosol type 2 source/gain accumulated 211018: - aergn03diff - Aerosol type 3 source/gain accumulated 211019: - aergn04diff - Aerosol type 4 source/gain accumulated 211020: - aergn05diff - Aerosol type 5 source/gain accumulated 211021: - aergn06diff - Aerosol type 6 source/gain accumulated 211022: - aergn07diff - Aerosol type 7 source/gain accumulated 211023: - aergn08diff - Aerosol type 8 source/gain accumulated 211024: - aergn09diff - Aerosol type 9 source/gain accumulated 211025: - aergn10diff - Aerosol type 10 source/gain accumulated 211026: - aergn11diff - Aerosol type 11 source/gain accumulated 211027: - aergn12diff - Aerosol type 12 source/gain accumulated 211028: - aerpr03diff - SO4 aerosol precursor mass mixing ratio 211029: - aerwv01diff - Water vapour mixing ratio for hydrophilic aerosols in mode 1 211030: - aerwv02diff - Water vapour mixing ratio for hydrophilic aerosols in mode 2 211031: - aerls01diff - Aerosol type 1 sink/loss accumulated 211032: - aerls02diff - Aerosol type 2 sink/loss accumulated 211033: - aerls03diff - Aerosol type 3 sink/loss accumulated 211034: - aerls04diff - Aerosol type 4 sink/loss accumulated 211035: - aerls05diff - Aerosol type 5 sink/loss accumulated 211036: - aerls06diff - Aerosol type 6 sink/loss accumulated 211037: - aerls07diff - Aerosol type 7 sink/loss accumulated 211038: - aerls08diff - Aerosol type 8 sink/loss accumulated 211039: - aerls09diff - Aerosol type 9 sink/loss accumulated 211040: - aerls10diff - Aerosol type 10 sink/loss accumulated 211041: - aerls11diff - Aerosol type 11 sink/loss accumulated 211042: - aerls12diff - Aerosol type 12 sink/loss accumulated 211043: - emdmsdiff - DMS surface emission 211044: - aerwv03diff - Water vapour mixing ratio for hydrophilic aerosols in mode 3 211045: - aerwv04diff - Water vapour mixing ratio for hydrophilic aerosols in mode 4 211046: - aerprdiff - Aerosol precursor mixing ratio 211047: - aersmdiff - Aerosol small mode mixing ratio 211048: - aerlgdiff - Aerosol large mode mixing ratio 211049: - aodprdiff - Aerosol precursor optical depth 211050: - aodsmdiff - Aerosol small mode optical depth 211051: - aodlgdiff - Aerosol large mode optical depth 211052: - aerdepdiff - Dust emission potential 211053: - aerltsdiff - Lifting threshold speed 211054: - aersccdiff - Soil clay content 211055: - _param_211055 - Experimental product 211056: - _param_211056 - Experimental product 211059: - h2odiff - Water vapour (chemistry) difference 211061: - co2diff - Carbon Dioxide 211062: - ch4diff - Methane 211063: - n2odiff - Nitrous oxide 211064: - tcco2diff - Total column Carbon Dioxide 211065: - tcch4diff - Total column Methane 211066: - tcn2odiff - Total column Nitrous oxide 211067: - co2ofdiff - Ocean flux of Carbon Dioxide 211068: - co2nbfdiff - Natural biosphere flux of Carbon Dioxide 211069: - co2apfdiff - Anthropogenic emissions of Carbon Dioxide 211070: - ch4fdiff - Methane Surface Fluxes 211071: - kch4diff - Methane loss rate due to radical hydroxyl (OH) 211080: - co2firediff - Wildfire flux of Carbon Dioxide 211081: - cofirediff - Wildfire flux of Carbon Monoxide 211082: - ch4firediff - Wildfire flux of Methane 211083: - nmhcfirediff - Wildfire flux of Non-Methane Hydro-Carbons 211084: - h2firediff - Wildfire flux of Hydrogen 211085: - noxfirediff - Wildfire flux of Nitrogen Oxides NOx 211086: - n2ofirediff - Wildfire flux of Nitrous Oxide 211087: - pm2p5firediff - Wildfire flux of Particulate Matter PM2.5 211088: - tpmfirediff - Wildfire flux of Total Particulate Matter 211089: - tcfirediff - Wildfire flux of Total Carbon in Aerosols 211090: - ocfirediff - Wildfire flux of Organic Carbon 211091: - bcfirediff - Wildfire flux of Black Carbon 211092: - cfirediff - Wildfire overall flux of burnt Carbon 211093: - c4ffirediff - Wildfire fraction of C4 plants 211094: - vegfirediff - Wildfire vegetation map index 211095: - ccfirediff - Wildfire Combustion Completeness 211096: - flfirediff - 'Wildfire Fuel Load: Carbon per unit area' 211097: - offirediff - Wildfire fraction of area observed 211098: - oafirediff - Wildfire observed area 211099: - frpfirediff - Wildfire radiative power 211100: - crfirediff - Wildfire combustion rate 211101: - maxfrpfirediff - Wildfire radiative power maximum 211102: - so2firediff - Wildfire flux of Sulfur Dioxide 211103: - ch3ohfirediff - Wildfire Flux of Methanol (CH3OH) 211104: - c2h5ohfirediff - Wildfire Flux of Ethanol (C2H5OH) 211105: - c3h8firediff - Wildfire Flux of Propane (C3H8) 211106: - c2h4firediff - Wildfire Flux of Ethene (C2H4) 211107: - c3h6firediff - Wildfire Flux of Propene (C3H6) 211108: - c5h8firediff - Wildfire Flux of Isoprene (C5H8) 211109: - terpenesfirediff - Wildfire Flux of Terpenes (C5H8)n 211110: - toluenefirediff - Wildfire Flux of Toluene_lump (C7H8+ C6H6 + C8H10) 211111: - hialkenesfirediff - Wildfire Flux of Higher Alkenes (CnH2n, C>=4) 211112: - hialkanesfirediff - Wildfire Flux of Higher Alkanes (CnH2n+2, C>=4) 211113: - ch2ofirediff - Wildfire Flux of Formaldehyde (CH2O) 211114: - c2h4ofirediff - Wildfire Flux of Acetaldehyde (C2H4O) 211115: - c3h6ofirediff - Wildfire Flux of Acetone (C3H6O) 211116: - nh3firediff - Wildfire Flux of Ammonia (NH3) 211117: - c2h6sfirediff - Wildfire Flux of Dimethyl Sulfide (DMS) (C2H6S) 211118: - c2h6firediff - Wildfire Flux of Ethane (C2H6) 211119: - alediff - Altitude of emitter 211120: - aptdiff - Altitude of plume top 211121: - no2diff - Nitrogen dioxide mass mixing ratio difference 211122: - so2diff - Sulphur dioxide mass mixing ratio difference 211123: - codiff - Carbon monoxide mass mixing ratio difference 211124: - hchodiff - Formaldehyde 211125: - tcno2diff - Total column Nitrogen dioxide 211126: - tcso2diff - Total column Sulphur dioxide 211127: - tccodiff - Total column Carbon monoxide 211128: - tchchodiff - Total column Formaldehyde 211129: - noxdiff - Nitrogen Oxides 211130: - tcnoxdiff - Total Column Nitrogen Oxides 211131: - grg1diff - Reactive tracer 1 mass mixing ratio 211132: - tcgrg1diff - Total column GRG tracer 1 211133: - grg2diff - Reactive tracer 2 mass mixing ratio 211134: - tcgrg2diff - Total column GRG tracer 2 211135: - grg3diff - Reactive tracer 3 mass mixing ratio 211136: - tcgrg3diff - Total column GRG tracer 3 211137: - grg4diff - Reactive tracer 4 mass mixing ratio 211138: - tcgrg4diff - Total column GRG tracer 4 211139: - grg5diff - Reactive tracer 5 mass mixing ratio 211140: - tcgrg5diff - Total column GRG tracer 5 211141: - grg6diff - Reactive tracer 6 mass mixing ratio 211142: - tcgrg6diff - Total column GRG tracer 6 211143: - grg7diff - Reactive tracer 7 mass mixing ratio 211144: - tcgrg7diff - Total column GRG tracer 7 211145: - grg8diff - Reactive tracer 8 mass mixing ratio 211146: - tcgrg8diff - Total column GRG tracer 8 211147: - grg9diff - Reactive tracer 9 mass mixing ratio 211148: - tcgrg9diff - Total column GRG tracer 9 211149: - grg10diff - Reactive tracer 10 mass mixing ratio 211150: - tcgrg10diff - Total column GRG tracer 10 211151: - sfnoxdiff - Surface flux Nitrogen oxides 211152: - sfno2diff - Surface flux Nitrogen dioxide 211153: - sfso2diff - Surface flux Sulphur dioxide 211154: - sfco2diff - Surface flux Carbon monoxide 211155: - sfhchodiff - Surface flux Formaldehyde 211156: - sfgo3diff - Surface flux GEMS Ozone 211157: - sfgr1diff - Surface flux reactive tracer 1 211158: - sfgr2diff - Surface flux reactive tracer 2 211159: - sfgr3diff - Surface flux reactive tracer 3 211160: - sfgr4diff - Surface flux reactive tracer 4 211161: - sfgr5diff - Surface flux reactive tracer 5 211162: - sfgr6diff - Surface flux reactive tracer 6 211163: - sfgr7diff - Surface flux reactive tracer 7 211164: - sfgr8diff - Surface flux reactive tracer 8 211165: - sfgr9diff - Surface flux reactive tracer 9 211166: - sfgr10diff - Surface flux reactive tracer 10 211170: - vso2diff - Volcanic sulfur dioxide mass mixing ratio increment 211181: - radiff - Radon 211182: - sf6diff - Sulphur Hexafluoride 211183: - tcradiff - Total column Radon 211184: - tcsf6diff - Total column Sulphur Hexafluoride 211185: - sf6apfdiff - Anthropogenic Emissions of Sulphur Hexafluoride 211203: - go3diff - Ozone mass mixing ratio difference (full chemistry scheme) 211206: - gtco3diff - GEMS Total column ozone 211207: - aod550diff - Total Aerosol Optical Depth at 550nm 211208: - ssaod550diff - Sea Salt Aerosol Optical Depth at 550nm 211209: - duaod550diff - Dust Aerosol Optical Depth at 550nm 211210: - omaod550diff - Organic Matter Aerosol Optical Depth at 550nm 211211: - bcaod550diff - Black Carbon Aerosol Optical Depth at 550nm 211212: - suaod550diff - Sulphate Aerosol Optical Depth at 550nm 211213: - aod469diff - Total Aerosol Optical Depth at 469nm 211214: - aod670diff - Total Aerosol Optical Depth at 670nm 211215: - aod865diff - Total Aerosol Optical Depth at 865nm 211216: - aod1240diff - Total Aerosol Optical Depth at 1240nm 211247: - aermr16diff - Nitrate fine mode aerosol mass mixing ratio 211248: - aermr17diff - Nitrate coarse mode aerosol mass mixing ratio 211249: - aermr18diff - Ammonium aerosol mass mixing ratio 211252: - aermr19diff - Biogenic secondary organic aerosol mass mixing ratio increment 211253: - aermr20diff - Anthropogenic secondary organic aerosol mass mixing ratio increment 212001: - _param_212001 - Experimental product 212002: - _param_212002 - Experimental product 212003: - _param_212003 - Experimental product 212004: - _param_212004 - Experimental product 212005: - _param_212005 - Experimental product 212006: - _param_212006 - Experimental product 212007: - _param_212007 - Experimental product 212008: - _param_212008 - Experimental product 212009: - _param_212009 - Experimental product 212010: - _param_212010 - Experimental product 212011: - _param_212011 - Experimental product 212012: - _param_212012 - Experimental product 212013: - _param_212013 - Experimental product 212014: - _param_212014 - Experimental product 212015: - _param_212015 - Experimental product 212016: - _param_212016 - Experimental product 212017: - _param_212017 - Experimental product 212018: - _param_212018 - Experimental product 212019: - _param_212019 - Experimental product 212020: - _param_212020 - Experimental product 212021: - _param_212021 - Experimental product 212022: - _param_212022 - Experimental product 212023: - _param_212023 - Experimental product 212024: - _param_212024 - Experimental product 212025: - _param_212025 - Experimental product 212026: - _param_212026 - Experimental product 212027: - _param_212027 - Experimental product 212028: - _param_212028 - Experimental product 212029: - _param_212029 - Experimental product 212030: - _param_212030 - Experimental product 212031: - _param_212031 - Experimental product 212032: - _param_212032 - Experimental product 212033: - _param_212033 - Experimental product 212034: - _param_212034 - Experimental product 212035: - _param_212035 - Experimental product 212036: - _param_212036 - Experimental product 212037: - _param_212037 - Experimental product 212038: - _param_212038 - Experimental product 212039: - _param_212039 - Experimental product 212040: - _param_212040 - Experimental product 212041: - _param_212041 - Experimental product 212042: - _param_212042 - Experimental product 212043: - _param_212043 - Experimental product 212044: - _param_212044 - Experimental product 212045: - _param_212045 - Experimental product 212046: - _param_212046 - Experimental product 212047: - _param_212047 - Experimental product 212048: - _param_212048 - Experimental product 212049: - _param_212049 - Experimental product 212050: - _param_212050 - Experimental product 212051: - _param_212051 - Experimental product 212052: - _param_212052 - Experimental product 212053: - _param_212053 - Experimental product 212054: - _param_212054 - Experimental product 212055: - _param_212055 - Experimental product 212056: - _param_212056 - Experimental product 212057: - _param_212057 - Experimental product 212058: - _param_212058 - Experimental product 212059: - _param_212059 - Experimental product 212060: - _param_212060 - Experimental product 212061: - _param_212061 - Experimental product 212062: - _param_212062 - Experimental product 212063: - _param_212063 - Experimental product 212064: - _param_212064 - Experimental product 212065: - _param_212065 - Experimental product 212066: - _param_212066 - Experimental product 212067: - _param_212067 - Experimental product 212068: - _param_212068 - Experimental product 212069: - _param_212069 - Experimental product 212070: - _param_212070 - Experimental product 212071: - _param_212071 - Experimental product 212072: - _param_212072 - Experimental product 212073: - _param_212073 - Experimental product 212074: - _param_212074 - Experimental product 212075: - _param_212075 - Experimental product 212076: - _param_212076 - Experimental product 212077: - _param_212077 - Experimental product 212078: - _param_212078 - Experimental product 212079: - _param_212079 - Experimental product 212080: - _param_212080 - Experimental product 212081: - _param_212081 - Experimental product 212082: - _param_212082 - Experimental product 212083: - _param_212083 - Experimental product 212084: - _param_212084 - Experimental product 212085: - _param_212085 - Experimental product 212086: - _param_212086 - Experimental product 212087: - _param_212087 - Experimental product 212088: - _param_212088 - Experimental product 212089: - _param_212089 - Experimental product 212090: - _param_212090 - Experimental product 212091: - _param_212091 - Experimental product 212092: - _param_212092 - Experimental product 212093: - _param_212093 - Experimental product 212094: - _param_212094 - Experimental product 212095: - _param_212095 - Experimental product 212096: - _param_212096 - Experimental product 212097: - _param_212097 - Experimental product 212098: - _param_212098 - Experimental product 212099: - _param_212099 - Experimental product 212100: - _param_212100 - Experimental product 212101: - _param_212101 - Experimental product 212102: - _param_212102 - Experimental product 212103: - _param_212103 - Experimental product 212104: - _param_212104 - Experimental product 212105: - _param_212105 - Experimental product 212106: - _param_212106 - Experimental product 212107: - _param_212107 - Experimental product 212108: - _param_212108 - Experimental product 212109: - _param_212109 - Experimental product 212110: - _param_212110 - Experimental product 212111: - _param_212111 - Experimental product 212112: - _param_212112 - Experimental product 212113: - _param_212113 - Experimental product 212114: - _param_212114 - Experimental product 212115: - _param_212115 - Experimental product 212116: - _param_212116 - Experimental product 212117: - _param_212117 - Experimental product 212118: - _param_212118 - Experimental product 212119: - _param_212119 - Experimental product 212120: - _param_212120 - Experimental product 212121: - _param_212121 - Experimental product 212122: - _param_212122 - Experimental product 212123: - _param_212123 - Experimental product 212124: - _param_212124 - Experimental product 212125: - _param_212125 - Experimental product 212126: - _param_212126 - Experimental product 212127: - _param_212127 - Experimental product 212128: - _param_212128 - Experimental product 212129: - _param_212129 - Experimental product 212130: - _param_212130 - Experimental product 212131: - _param_212131 - Experimental product 212132: - _param_212132 - Experimental product 212133: - _param_212133 - Experimental product 212134: - _param_212134 - Experimental product 212135: - _param_212135 - Experimental product 212136: - _param_212136 - Experimental product 212137: - _param_212137 - Experimental product 212138: - _param_212138 - Experimental product 212139: - _param_212139 - Experimental product 212140: - _param_212140 - Experimental product 212141: - _param_212141 - Experimental product 212142: - _param_212142 - Experimental product 212143: - _param_212143 - Experimental product 212144: - _param_212144 - Experimental product 212145: - _param_212145 - Experimental product 212146: - _param_212146 - Experimental product 212147: - _param_212147 - Experimental product 212148: - _param_212148 - Experimental product 212149: - _param_212149 - Experimental product 212150: - _param_212150 - Experimental product 212151: - _param_212151 - Experimental product 212152: - _param_212152 - Experimental product 212153: - _param_212153 - Experimental product 212154: - _param_212154 - Experimental product 212155: - _param_212155 - Experimental product 212156: - _param_212156 - Experimental product 212157: - _param_212157 - Experimental product 212158: - _param_212158 - Experimental product 212159: - _param_212159 - Experimental product 212160: - _param_212160 - Experimental product 212161: - _param_212161 - Experimental product 212162: - _param_212162 - Experimental product 212163: - _param_212163 - Experimental product 212164: - _param_212164 - Experimental product 212165: - _param_212165 - Experimental product 212166: - _param_212166 - Experimental product 212167: - _param_212167 - Experimental product 212168: - _param_212168 - Experimental product 212169: - _param_212169 - Experimental product 212170: - _param_212170 - Experimental product 212171: - _param_212171 - Experimental product 212172: - _param_212172 - Experimental product 212173: - _param_212173 - Experimental product 212174: - _param_212174 - Experimental product 212175: - _param_212175 - Experimental product 212176: - _param_212176 - Experimental product 212177: - _param_212177 - Experimental product 212178: - _param_212178 - Experimental product 212179: - _param_212179 - Experimental product 212180: - _param_212180 - Experimental product 212181: - _param_212181 - Experimental product 212182: - _param_212182 - Experimental product 212183: - _param_212183 - Experimental product 212184: - _param_212184 - Experimental product 212185: - _param_212185 - Experimental product 212186: - _param_212186 - Experimental product 212187: - _param_212187 - Experimental product 212188: - _param_212188 - Experimental product 212189: - _param_212189 - Experimental product 212190: - _param_212190 - Experimental product 212191: - _param_212191 - Experimental product 212192: - _param_212192 - Experimental product 212193: - _param_212193 - Experimental product 212194: - _param_212194 - Experimental product 212195: - _param_212195 - Experimental product 212196: - _param_212196 - Experimental product 212197: - _param_212197 - Experimental product 212198: - _param_212198 - Experimental product 212199: - _param_212199 - Experimental product 212200: - _param_212200 - Experimental product 212201: - _param_212201 - Experimental product 212202: - _param_212202 - Experimental product 212203: - _param_212203 - Experimental product 212204: - _param_212204 - Experimental product 212205: - _param_212205 - Experimental product 212206: - _param_212206 - Experimental product 212207: - _param_212207 - Experimental product 212208: - _param_212208 - Experimental product 212209: - _param_212209 - Experimental product 212210: - _param_212210 - Experimental product 212211: - _param_212211 - Experimental product 212212: - _param_212212 - Experimental product 212213: - _param_212213 - Experimental product 212214: - _param_212214 - Experimental product 212215: - _param_212215 - Experimental product 212216: - _param_212216 - Experimental product 212217: - _param_212217 - Experimental product 212218: - _param_212218 - Experimental product 212219: - _param_212219 - Experimental product 212220: - _param_212220 - Experimental product 212221: - _param_212221 - Experimental product 212222: - _param_212222 - Experimental product 212223: - _param_212223 - Experimental product 212224: - _param_212224 - Experimental product 212225: - _param_212225 - Experimental product 212226: - _param_212226 - Experimental product 212227: - _param_212227 - Experimental product 212228: - _param_212228 - Experimental product 212229: - _param_212229 - Experimental product 212230: - _param_212230 - Experimental product 212231: - _param_212231 - Experimental product 212232: - _param_212232 - Experimental product 212233: - _param_212233 - Experimental product 212234: - _param_212234 - Experimental product 212235: - _param_212235 - Experimental product 212236: - _param_212236 - Experimental product 212237: - _param_212237 - Experimental product 212238: - _param_212238 - Experimental product 212239: - _param_212239 - Experimental product 212240: - _param_212240 - Experimental product 212241: - _param_212241 - Experimental product 212242: - _param_212242 - Experimental product 212243: - _param_212243 - Experimental product 212244: - _param_212244 - Experimental product 212245: - _param_212245 - Experimental product 212246: - _param_212246 - Experimental product 212247: - _param_212247 - Experimental product 212248: - _param_212248 - Experimental product 212249: - _param_212249 - Experimental product 212250: - _param_212250 - Experimental product 212251: - _param_212251 - Experimental product 212252: - _param_212252 - Experimental product 212253: - _param_212253 - Experimental product 212254: - _param_212254 - Experimental product 212255: - _param_212255 - Experimental product 213001: - sppt1 - Random pattern 1 for sppt 213002: - sppt2 - Random pattern 2 for sppt 213003: - sppt3 - Random pattern 3 for sppt 213004: - sppt4 - Random pattern 4 for sppt 213005: - sppt5 - Random pattern 5 for sppt 213101: - spp1 - Random pattern 1 for SPP scheme 213102: - spp2 - Random pattern 2 for SPP scheme 213103: - spp3 - Random pattern 3 for SPP scheme 213104: - spp4 - Random pattern 4 for SPP scheme 213105: - spp5 - Random pattern 5 for SPP scheme 213106: - spp6 - Random pattern 6 for SPP scheme 213107: - spp7 - Random pattern 7 for SPP scheme 213108: - spp8 - Random pattern 8 for SPP scheme 213109: - spp9 - Random pattern 9 for SPP scheme 213110: - spp10 - Random pattern 10 for SPP scheme 213111: - spp11 - Random pattern 11 for SPP scheme 213112: - spp12 - Random pattern 12 for SPP scheme 213113: - spp13 - Random pattern 13 for SPP scheme 213114: - spp14 - Random pattern 14 for SPP scheme 213115: - spp15 - Random pattern 15 for SPP scheme 213116: - spp16 - Random pattern 16 for SPP scheme 213117: - spp17 - Random pattern 17 for SPP scheme 213118: - spp18 - Random pattern 18 for SPP scheme 213119: - spp19 - Random pattern 19 for SPP scheme 213120: - spp20 - Random pattern 20 for SPP scheme 213121: - spp21 - Random pattern 21 for SPP scheme 213122: - spp22 - Random pattern 22 for SPP scheme 213123: - spp23 - Random pattern 23 for SPP scheme 213124: - spp24 - Random pattern 24 for SPP scheme 213125: - spp25 - Random pattern 25 for SPP scheme 213126: - spp26 - Random pattern 26 for SPP scheme 213127: - spp27 - Random pattern 27 for SPP scheme 213128: - spp28 - Random pattern 28 for SPP scheme 213129: - spp29 - Random pattern 29 for SPP scheme 213130: - spp30 - Random pattern 30 for SPP scheme 213131: - spp31 - Random pattern 31 for SPP scheme 213132: - spp32 - Random pattern 32 for SPP scheme 213133: - spp33 - Random pattern 33 for SPP scheme 213134: - spp34 - Random pattern 34 for SPP scheme 213135: - spp35 - Random pattern 35 for SPP scheme 213136: - spp36 - Random pattern 36 for SPP scheme 213137: - spp37 - Random pattern 37 for SPP scheme 213138: - spp38 - Random pattern 38 for SPP scheme 213139: - spp39 - Random pattern 39 for SPP scheme 213140: - spp40 - Random pattern 40 for SPP scheme 213141: - spp41 - Random pattern 41 for SPP scheme 213142: - spp42 - Random pattern 42 for SPP scheme 213143: - spp43 - Random pattern 43 for SPP scheme 213144: - spp44 - Random pattern 44 for SPP scheme 213145: - spp45 - Random pattern 45 for SPP scheme 213146: - spp46 - Random pattern 46 for SPP scheme 213147: - spp47 - Random pattern 47 for SPP scheme 213148: - spp48 - Random pattern 48 for SPP scheme 213149: - spp49 - Random pattern 49 for SPP scheme 213150: - spp50 - Random pattern 50 for SPP scheme 213151: - spp51 - Random pattern 51 for SPP scheme 213152: - spp52 - Random pattern 52 for SPP scheme 213153: - spp53 - Random pattern 53 for SPP scheme 213154: - spp54 - Random pattern 54 for SPP scheme 213155: - spp55 - Random pattern 55 for SPP scheme 213156: - spp56 - Random pattern 56 for SPP scheme 213157: - spp57 - Random pattern 57 for SPP scheme 213158: - spp58 - Random pattern 58 for SPP scheme 213159: - spp59 - Random pattern 59 for SPP scheme 213160: - spp60 - Random pattern 60 for SPP scheme 213161: - spp61 - Random pattern 61 for SPP scheme 213162: - spp62 - Random pattern 62 for SPP scheme 213163: - spp63 - Random pattern 63 for SPP scheme 213164: - spp64 - Random pattern 64 for SPP scheme 213165: - spp65 - Random pattern 65 for SPP scheme 213166: - spp66 - Random pattern 66 for SPP scheme 213167: - spp67 - Random pattern 67 for SPP scheme 213168: - spp68 - Random pattern 68 for SPP scheme 213169: - spp69 - Random pattern 69 for SPP scheme 213170: - spp70 - Random pattern 70 for SPP scheme 213171: - spp71 - Random pattern 71 for SPP scheme 213172: - spp72 - Random pattern 72 for SPP scheme 213173: - spp73 - Random pattern 73 for SPP scheme 213174: - spp74 - Random pattern 74 for SPP scheme 213175: - spp75 - Random pattern 75 for SPP scheme 213176: - spp76 - Random pattern 76 for SPP scheme 213177: - spp77 - Random pattern 77 for SPP scheme 213178: - spp78 - Random pattern 78 for SPP scheme 213179: - spp79 - Random pattern 79 for SPP scheme 213180: - spp80 - Random pattern 80 for SPP scheme 213181: - spp81 - Random pattern 81 for SPP scheme 213182: - spp82 - Random pattern 82 for SPP scheme 213183: - spp83 - Random pattern 83 for SPP scheme 213184: - spp84 - Random pattern 84 for SPP scheme 213185: - spp85 - Random pattern 85 for SPP scheme 213186: - spp86 - Random pattern 86 for SPP scheme 213187: - spp87 - Random pattern 87 for SPP scheme 213188: - spp88 - Random pattern 88 for SPP scheme 213189: - spp89 - Random pattern 89 for SPP scheme 213190: - spp90 - Random pattern 90 for SPP scheme 213191: - spp91 - Random pattern 91 for SPP scheme 213192: - spp92 - Random pattern 92 for SPP scheme 213193: - spp93 - Random pattern 93 for SPP scheme 213194: - spp94 - Random pattern 94 for SPP scheme 213195: - spp95 - Random pattern 95 for SPP scheme 213196: - spp96 - Random pattern 96 for SPP scheme 213197: - spp97 - Random pattern 97 for SPP scheme 213198: - spp98 - Random pattern 98 for SPP scheme 213199: - spp99 - Random pattern 99 for SPP scheme 213200: - spp100 - Random pattern 100 for SPP scheme 213201: - spp101 - Random pattern 101 for SPP scheme 213202: - spp102 - Random pattern 102 for SPP scheme 213203: - spp103 - Random pattern 103 for SPP scheme 213204: - spp104 - Random pattern 104 for SPP scheme 213205: - spp105 - Random pattern 105 for SPP scheme 213206: - spp106 - Random pattern 106 for SPP scheme 213207: - spp107 - Random pattern 107 for SPP scheme 213208: - spp108 - Random pattern 108 for SPP scheme 213209: - spp109 - Random pattern 109 for SPP scheme 213210: - spp110 - Random pattern 110 for SPP scheme 213211: - spp111 - Random pattern 111 for SPP scheme 213212: - spp112 - Random pattern 112 for SPP scheme 213213: - spp113 - Random pattern 113 for SPP scheme 213214: - spp114 - Random pattern 114 for SPP scheme 213215: - spp115 - Random pattern 115 for SPP scheme 213216: - spp116 - Random pattern 116 for SPP scheme 213217: - spp117 - Random pattern 117 for SPP scheme 213218: - spp118 - Random pattern 118 for SPP scheme 213219: - spp119 - Random pattern 119 for SPP scheme 213220: - spp120 - Random pattern 120 for SPP scheme 213221: - spp121 - Random pattern 121 for SPP scheme 214001: - cossza - Cosine of solar zenith angle 214002: - uvbed - UV biologically effective dose 214003: - uvbedcs - UV biologically effective dose clear-sky 214004: - uvsflxt280285 - Total surface UV spectral flux (280-285 nm) 214005: - uvsflxt285290 - Total surface UV spectral flux (285-290 nm) 214006: - uvsflxt290295 - Total surface UV spectral flux (290-295 nm) 214007: - uvsflxt295300 - Total surface UV spectral flux (295-300 nm) 214008: - uvsflxt300305 - Total surface UV spectral flux (300-305 nm) 214009: - uvsflxt305310 - Total surface UV spectral flux (305-310 nm) 214010: - uvsflxt310315 - Total surface UV spectral flux (310-315 nm) 214011: - uvsflxt315320 - Total surface UV spectral flux (315-320 nm) 214012: - uvsflxt320325 - Total surface UV spectral flux (320-325 nm) 214013: - uvsflxt325330 - Total surface UV spectral flux (325-330 nm) 214014: - uvsflxt330335 - Total surface UV spectral flux (330-335 nm) 214015: - uvsflxt335340 - Total surface UV spectral flux (335-340 nm) 214016: - uvsflxt340345 - Total surface UV spectral flux (340-345 nm) 214017: - uvsflxt345350 - Total surface UV spectral flux (345-350 nm) 214018: - uvsflxt350355 - Total surface UV spectral flux (350-355 nm) 214019: - uvsflxt355360 - Total surface UV spectral flux (355-360 nm) 214020: - uvsflxt360365 - Total surface UV spectral flux (360-365 nm) 214021: - uvsflxt365370 - Total surface UV spectral flux (365-370 nm) 214022: - uvsflxt370375 - Total surface UV spectral flux (370-375 nm) 214023: - uvsflxt375380 - Total surface UV spectral flux (375-380 nm) 214024: - uvsflxt380385 - Total surface UV spectral flux (380-385 nm) 214025: - uvsflxt385390 - Total surface UV spectral flux (385-390 nm) 214026: - uvsflxt390395 - Total surface UV spectral flux (390-395 nm) 214027: - uvsflxt395400 - Total surface UV spectral flux (395-400 nm) 214028: - uvsflxcs280285 - Clear-sky surface UV spectral flux (280-285 nm) 214029: - uvsflxcs285290 - Clear-sky surface UV spectral flux (285-290 nm) 214030: - uvsflxcs290295 - Clear-sky surface UV spectral flux (290-295 nm) 214031: - uvsflxcs295300 - Clear-sky surface UV spectral flux (295-300 nm) 214032: - uvsflxcs300305 - Clear-sky surface UV spectral flux (300-305 nm) 214033: - uvsflxcs305310 - Clear-sky surface UV spectral flux (305-310 nm) 214034: - uvsflxcs310315 - Clear-sky surface UV spectral flux (310-315 nm) 214035: - uvsflxcs315320 - Clear-sky surface UV spectral flux (315-320 nm) 214036: - uvsflxcs320325 - Clear-sky surface UV spectral flux (320-325 nm) 214037: - uvsflxcs325330 - Clear-sky surface UV spectral flux (325-330 nm) 214038: - uvsflxcs330335 - Clear-sky surface UV spectral flux (330-335 nm) 214039: - uvsflxcs335340 - Clear-sky surface UV spectral flux (335-340 nm) 214040: - uvsflxcs340345 - Clear-sky surface UV spectral flux (340-345 nm) 214041: - uvsflxcs345350 - Clear-sky surface UV spectral flux (345-350 nm) 214042: - uvsflxcs350355 - Clear-sky surface UV spectral flux (350-355 nm) 214043: - uvsflxcs355360 - Clear-sky surface UV spectral flux (355-360 nm) 214044: - uvsflxcs360365 - Clear-sky surface UV spectral flux (360-365 nm) 214045: - uvsflxcs365370 - Clear-sky surface UV spectral flux (365-370 nm) 214046: - uvsflxcs370375 - Clear-sky surface UV spectral flux (370-375 nm) 214047: - uvsflxcs375380 - Clear-sky surface UV spectral flux (375-380 nm) 214048: - uvsflxcs380385 - Clear-sky surface UV spectral flux (380-385 nm) 214049: - uvsflxcs385390 - Clear-sky surface UV spectral flux (385-390 nm) 214050: - uvsflxcs390395 - Clear-sky surface UV spectral flux (390-395 nm) 214051: - uvsflxcs395400 - Clear-sky surface UV spectral flux (395-400 nm) 214052: - aot340 - Profile of optical thickness at 340 nm 215001: - aersrcsss - Source/gain of sea salt aerosol (0.03 - 0.5 um) 215002: - aersrcssm - Source/gain of sea salt aerosol (0.5 - 5 um) 215003: - aersrcssl - Source/gain of sea salt aerosol (5 - 20 um) 215004: - aerddpsss - Dry deposition of sea salt aerosol (0.03 - 0.5 um) 215005: - aerddpssm - Dry deposition of sea salt aerosol (0.5 - 5 um) 215006: - aerddpssl - Dry deposition of sea salt aerosol (5 - 20 um) 215007: - aersdmsss - Sedimentation of sea salt aerosol (0.03 - 0.5 um) 215008: - aersdmssm - Sedimentation of sea salt aerosol (0.5 - 5 um) 215009: - aersdmssl - Sedimentation of sea salt aerosol (5 - 20 um) 215010: - aerwdlssss - Wet deposition of sea salt aerosol (0.03 - 0.5 um) by large-scale precipitation 215011: - aerwdlsssm - Wet deposition of sea salt aerosol (0.5 - 5 um) by large-scale precipitation 215012: - aerwdlsssl - Wet deposition of sea salt aerosol (5 - 20 um) by large-scale precipitation 215013: - aerwdccsss - Wet deposition of sea salt aerosol (0.03 - 0.5 um) by convective precipitation 215014: - aerwdccssm - Wet deposition of sea salt aerosol (0.5 - 5 um) by convective precipitation 215015: - aerwdccssl - Wet deposition of sea salt aerosol (5 - 20 um) by convective precipitation 215016: - aerngtsss - Negative fixer of sea salt aerosol (0.03 - 0.5 um) 215017: - aerngtssm - Negative fixer of sea salt aerosol (0.5 - 5 um) 215018: - aerngtssl - Negative fixer of sea salt aerosol (5 - 20 um) 215019: - aermsssss - Vertically integrated mass of sea salt aerosol (0.03 - 0.5 um) 215020: - aermssssm - Vertically integrated mass of sea salt aerosol (0.5 - 5 um) 215021: - aermssssl - Vertically integrated mass of sea salt aerosol (5 - 20 um) 215022: - aerodsss - Sea salt aerosol (0.03 - 0.5 um) optical depth 215023: - aerodssm - Sea salt aerosol (0.5 - 5 um) optical depth 215024: - aerodssl - Sea salt aerosol (5 - 20 um) optical depth 215025: - aersrcdus - Source/gain of dust aerosol (0.03 - 0.55 um) 215026: - aersrcdum - Source/gain of dust aerosol (0.55 - 0.9 um) 215027: - aersrcdul - Source/gain of dust aerosol (0.9 - 20 um) 215028: - aerddpdus - Dry deposition of dust aerosol (0.03 - 0.55 um) 215029: - aerddpdum - Dry deposition of dust aerosol (0.55 - 0.9 um) 215030: - aerddpdul - Dry deposition of dust aerosol (0.9 - 20 um) 215031: - aersdmdus - Sedimentation of dust aerosol (0.03 - 0.55 um) 215032: - aersdmdum - Sedimentation of dust aerosol (0.55 - 0.9 um) 215033: - aersdmdul - Sedimentation of dust aerosol (0.9 - 20 um) 215034: - aerwdlsdus - Wet deposition of dust aerosol (0.03 - 0.55 um) by large-scale precipitation 215035: - aerwdlsdum - Wet deposition of dust aerosol (0.55 - 0.9 um) by large-scale precipitation 215036: - aerwdlsdul - Wet deposition of dust aerosol (0.9 - 20 um) by large-scale precipitation 215037: - aerwdccdus - Wet deposition of dust aerosol (0.03 - 0.55 um) by convective precipitation 215038: - aerwdccdum - Wet deposition of dust aerosol (0.55 - 0.9 um) by convective precipitation 215039: - aerwdccdul - Wet deposition of dust aerosol (0.9 - 20 um) by convective precipitation 215040: - aerngtdus - Negative fixer of dust aerosol (0.03 - 0.55 um) 215041: - aerngtdum - Negative fixer of dust aerosol (0.55 - 0.9 um) 215042: - aerngtdul - Negative fixer of dust aerosol (0.9 - 20 um) 215043: - aermssdus - Vertically integrated mass of dust aerosol (0.03 - 0.55 um) 215044: - aermssdum - Vertically integrated mass of dust aerosol (0.55 - 0.9 um) 215045: - aermssdul - Vertically integrated mass of dust aerosol (0.9 - 20 um) 215046: - aeroddus - Dust aerosol (0.03 - 0.55 um) optical depth 215047: - aeroddum - Dust aerosol (0.55 - 0.9 um) optical depth 215048: - aeroddul - Dust aerosol (0.9 - 20 um) optical depth 215049: - aersrcomhphob - Source/gain of hydrophobic organic matter aerosol 215050: - aersrcomhphil - Source/gain of hydrophilic organic matter aerosol 215051: - aerddpomhphob - Dry deposition of hydrophobic organic matter aerosol 215052: - aerddpomhphil - Dry deposition of hydrophilic organic matter aerosol 215053: - aersdmomhphob - Sedimentation of hydrophobic organic matter aerosol 215054: - aersdmomhphil - Sedimentation of hydrophilic organic matter aerosol 215055: - aerwdlsomhphob - Wet deposition of hydrophobic organic matter aerosol by large-scale precipitation 215056: - aerwdlsomhphil - Wet deposition of hydrophilic organic matter aerosol by large-scale precipitation 215057: - aerwdccomhphob - Wet deposition of hydrophobic organic matter aerosol by convective precipitation 215058: - aerwdccomhphil - Wet deposition of hydrophilic organic matter aerosol by convective precipitation 215059: - aerngtomhphob - Negative fixer of hydrophobic organic matter aerosol 215060: - aerngtomhphil - Negative fixer of hydrophilic organic matter aerosol 215061: - aermssomhphob - Vertically integrated mass of hydrophobic organic matter aerosol 215062: - aermssomhphil - Vertically integrated mass of hydrophilic organic matter aerosol 215063: - aerodomhphob - Hydrophobic organic matter aerosol optical depth 215064: - aerodomhphil - Hydrophilic organic matter aerosol optical depth 215065: - aersrcbchphob - Source/gain of hydrophobic black carbon aerosol 215066: - aersrcbchphil - Source/gain of hydrophilic black carbon aerosol 215067: - aerddpbchphob - Dry deposition of hydrophobic black carbon aerosol 215068: - aerddpbchphil - Dry deposition of hydrophilic black carbon aerosol 215069: - aersdmbchphob - Sedimentation of hydrophobic black carbon aerosol 215070: - aersdmbchphil - Sedimentation of hydrophilic black carbon aerosol 215071: - aerwdlsbchphob - Wet deposition of hydrophobic black carbon aerosol by large-scale precipitation 215072: - aerwdlsbchphil - Wet deposition of hydrophilic black carbon aerosol by large-scale precipitation 215073: - aerwdccbchphob - Wet deposition of hydrophobic black carbon aerosol by convective precipitation 215074: - aerwdccbchphil - Wet deposition of hydrophilic black carbon aerosol by convective precipitation 215075: - aerngtbchphob - Negative fixer of hydrophobic black carbon aerosol 215076: - aerngtbchphil - Negative fixer of hydrophilic black carbon aerosol 215077: - aermssbchphob - Vertically integrated mass of hydrophobic black carbon aerosol 215078: - aermssbchphil - Vertically integrated mass of hydrophilic black carbon aerosol 215079: - aerodbchphob - Hydrophobic black carbon aerosol optical depth 215080: - aerodbchphil - Hydrophilic black carbon aerosol optical depth 215081: - aersrcsu - Source/gain of sulphate aerosol 215082: - aerddpsu - Dry deposition of sulphate aerosol 215083: - aersdmsu - Sedimentation of sulphate aerosol 215084: - aerwdlssu - Wet deposition of sulphate aerosol by large-scale precipitation 215085: - aerwdccsu - Wet deposition of sulphate aerosol by convective precipitation 215086: - aerngtsu - Negative fixer of sulphate aerosol 215087: - aermsssu - Vertically integrated mass of sulphate aerosol 215088: - aerodsu - Sulphate aerosol optical depth 215089: - accaod550 - Accumulated total aerosol optical depth at 550 nm 215090: - aluvpsn - Effective (snow effect included) UV visible albedo for direct radiation 215091: - aerdep10si - 10 metre wind speed dust emission potential 215092: - aerdep10fg - 10 metre wind gustiness dust emission potential 215093: - aot532 - Total aerosol optical thickness at 532 nm 215094: - naot532 - Natural (sea-salt and dust) aerosol optical thickness at 532 nm 215095: - aaot532 - Anthropogenic (black carbon, organic matter, sulphate) aerosol optical thickness at 532 nm 215096: - aodabs340 - Total absorption aerosol optical depth at 340 nm 215097: - aodabs355 - Total absorption aerosol optical depth at 355 nm 215098: - aodabs380 - Total absorption aerosol optical depth at 380 nm 215099: - aodabs400 - Total absorption aerosol optical depth at 400 nm 215100: - aodabs440 - Total absorption aerosol optical depth at 440 nm 215101: - aodabs469 - Total absorption aerosol optical depth at 469 nm 215102: - aodabs500 - Total absorption aerosol optical depth at 500 nm 215103: - aodabs532 - Total absorption aerosol optical depth at 532 nm 215104: - aodabs550 - Total absorption aerosol optical depth at 550 nm 215105: - aodabs645 - Total absorption aerosol optical depth at 645 nm 215106: - aodabs670 - Total absorption aerosol optical depth at 670 nm 215107: - aodabs800 - Total absorption aerosol optical depth at 800 nm 215108: - aodabs858 - Total absorption aerosol optical depth at 858 nm 215109: - aodabs865 - Total absorption aerosol optical depth at 865 nm 215110: - aodabs1020 - Total absorption aerosol optical depth at 1020 nm 215111: - aodabs1064 - Total absorption aerosol optical depth at 1064 nm 215112: - aodabs1240 - Total absorption aerosol optical depth at 1240 nm 215113: - aodabs1640 - Total absorption aerosol optical depth at 1640 nm 215114: - aodfm340 - Total fine mode (r < 0.5 um) aerosol optical depth at 340 nm 215115: - aodfm355 - Total fine mode (r < 0.5 um) aerosol optical depth at 355 nm 215116: - aodfm380 - Total fine mode (r < 0.5 um) aerosol optical depth at 380 nm 215117: - aodfm400 - Total fine mode (r < 0.5 um) aerosol optical depth at 400 nm 215118: - aodfm440 - Total fine mode (r < 0.5 um) aerosol optical depth at 440 nm 215119: - aodfm469 - Total fine mode (r < 0.5 um) aerosol optical depth at 469 nm 215120: - aodfm500 - Total fine mode (r < 0.5 um) aerosol optical depth at 500 nm 215121: - aodfm532 - Total fine mode (r < 0.5 um) aerosol optical depth at 532 nm 215122: - aodfm550 - Total fine mode (r < 0.5 um) aerosol optical depth at 550 nm 215123: - aodfm645 - Total fine mode (r < 0.5 um) aerosol optical depth at 645 nm 215124: - aodfm670 - Total fine mode (r < 0.5 um) aerosol optical depth at 670 nm 215125: - aodfm800 - Total fine mode (r < 0.5 um) aerosol optical depth at 800 nm 215126: - aodfm858 - Total fine mode (r < 0.5 um) aerosol optical depth at 858 nm 215127: - aodfm865 - Total fine mode (r < 0.5 um) aerosol optical depth at 865 nm 215128: - aodfm1020 - Total fine mode (r < 0.5 um) aerosol optical depth at 1020 nm 215129: - aodfm1064 - Total fine mode (r < 0.5 um) aerosol optical depth at 1064 nm 215130: - aodfm1240 - Total fine mode (r < 0.5 um) aerosol optical depth at 1240 nm 215131: - aodfm1640 - Total fine mode (r < 0.5 um) aerosol optical depth at 1640 nm 215132: - ssa340 - Single scattering albedo at 340 nm 215133: - ssa355 - Single scattering albedo at 355 nm 215134: - ssa380 - Single scattering albedo at 380 nm 215135: - ssa400 - Single scattering albedo at 400 nm 215136: - ssa440 - Single scattering albedo at 440 nm 215137: - ssa469 - Single scattering albedo at 469 nm 215138: - ssa500 - Single scattering albedo at 500 nm 215139: - ssa532 - Single scattering albedo at 532 nm 215140: - ssa550 - Single scattering albedo at 550 nm 215141: - ssa645 - Single scattering albedo at 645 nm 215142: - ssa670 - Single scattering albedo at 670 nm 215143: - ssa800 - Single scattering albedo at 800 nm 215144: - ssa858 - Single scattering albedo at 858 nm 215145: - ssa865 - Single scattering albedo at 865 nm 215146: - ssa1020 - Single scattering albedo at 1020 nm 215147: - ssa1064 - Single scattering albedo at 1064 nm 215148: - ssa1240 - Single scattering albedo at 1240 nm 215149: - ssa1640 - Single scattering albedo at 1640 nm 215150: - asymmetry340 - Asymmetry factor at 340 nm 215151: - asymmetry355 - Asymmetry factor at 355 nm 215152: - asymmetry380 - Asymmetry factor at 380 nm 215153: - asymmetry400 - Asymmetry factor at 400 nm 215154: - asymmetry440 - Asymmetry factor at 440 nm 215155: - asymmetry469 - Asymmetry factor at 469 nm 215156: - asymmetry500 - Asymmetry factor at 500 nm 215157: - asymmetry532 - Asymmetry factor at 532 nm 215158: - asymmetry550 - Asymmetry factor at 550 nm 215159: - asymmetry645 - Asymmetry factor at 645 nm 215160: - asymmetry670 - Asymmetry factor at 670 nm 215161: - asymmetry800 - Asymmetry factor at 800 nm 215162: - asymmetry858 - Asymmetry factor at 858 nm 215163: - asymmetry865 - Asymmetry factor at 865 nm 215164: - asymmetry1020 - Asymmetry factor at 1020 nm 215165: - asymmetry1064 - Asymmetry factor at 1064 nm 215166: - asymmetry1240 - Asymmetry factor at 1240 nm 215167: - asymmetry1640 - Asymmetry factor at 1640 nm 215168: - aersrcso2 - Source/gain of sulphur dioxide 215169: - aerddpso2 - Dry deposition of sulphur dioxide 215170: - aersdmso2 - Sedimentation of sulphur dioxide 215171: - aerwdlsso2 - Wet deposition of sulphur dioxide by large-scale precipitation 215172: - aerwdccso2 - Wet deposition of sulphur dioxide by convective precipitation 215173: - aerngtso2 - Negative fixer of sulphur dioxide 215174: - aermssso2 - Vertically integrated mass of sulphur dioxide 215175: - aerodso2 - Sulphur dioxide optical depth 215176: - aodabs2130 - Total absorption aerosol optical depth at 2130 nm 215177: - aodfm2130 - Total fine mode (r < 0.5 um) aerosol optical depth at 2130 nm 215178: - ssa2130 - Single scattering albedo at 2130 nm 215179: - asymmetry2130 - Asymmetry factor at 2130 nm 215180: - aerext355 - Aerosol extinction coefficient at 355 nm 215181: - aerext532 - Aerosol extinction coefficient at 532 nm 215182: - aerext1064 - Aerosol extinction coefficient at 1064 nm 215183: - aerbackscattoa355 - Aerosol backscatter coefficient at 355 nm (from top of atmosphere) 215184: - aerbackscattoa532 - Aerosol backscatter coefficient at 532 nm (from top of atmosphere) 215185: - aerbackscattoa1064 - Aerosol backscatter coefficient at 1064 nm (from top of atmosphere) 215186: - aerbackscatgnd355 - Aerosol backscatter coefficient at 355 nm (from ground) 215187: - aerbackscatgnd532 - Aerosol backscatter coefficient at 532 nm (from ground) 215188: - aerbackscatgnd1064 - Aerosol backscatter coefficient at 1064 nm (from ground) 215189: - aersrcnif - Source/gain of fine-mode nitrate aerosol 215190: - aersrcnic - Source/gain of coarse-mode nitrate aerosol 215191: - aerddpnif - Dry deposition of fine-mode nitrate aerosol 215192: - aerddpnic - Dry deposition of coarse-mode nitrate aerosol 215193: - aersdmnif - Sedimentation of fine-mode nitrate aerosol 215194: - aersdmnic - Sedimentation of coarse-mode nitrate aerosol 215195: - aerwdlnif - Wet deposition of fine-mode nitrate aerosol by large-scale precipitation 215196: - aerwdlnic - Wet deposition of coarse-mode nitrate aerosol by large-scale precipitation 215197: - aerwdcnif - Wet deposition of fine-mode nitrate aerosol by convective precipitation 215198: - aerwdcnic - Wet deposition of coarse-mode nitrate aerosol by convective precipitation 215199: - aerngtnif - Negative fixer of fine-mode nitrate aerosol 215200: - aerngtnic - Negative fixer of coarse-mode nitrate aerosol 215201: - aermssnif - Vertically integrated mass of fine-mode nitrate aerosol 215202: - aermssnic - Vertically integrated mass of coarse-mode nitrate aerosol 215203: - aerodnif - Fine-mode nitrate aerosol optical depth at 550 nm 215204: - aerodnic - Coarse-mode nitrate aerosol optical depth at 550 nm 215205: - aersrcam - Source/gain of ammonium aerosol 215206: - aerddpam - Dry deposition of ammonium aerosol 215207: - aersdmam - Sedimentation of ammonium aerosol 215208: - aerwdlam - Wet deposition of ammonium aerosol by large-scale precipitation 215209: - aerwdcam - Wet deposition of ammonium aerosol by convective precipitation 215210: - aerngtam - Negative fixer of ammonium aerosol 215211: - aermssam - Vertically integrated mass of ammonium aerosol 215212: - aersrcsoab - Source/gain of biogenic secondary organic aerosol 215213: - aerddpsoab - Dry deposition of biogenic secondary organic aerosol 215214: - aersdmsoab - Sedimentation of biogenic secondary organic aerosol 215215: - aerwdlsoab - Wet deposition of biogenic secondary organic aerosol by large-scale precipitation 215216: - aerwdcsoab - Wet deposition of biogenic secondary organic aerosol by convective precipitation 215217: - aerngtsoab - Negative fixer of biogenic secondary organic aerosol 215218: - aermsssoab - Vertically integrated mass of biogenic secondary organic aerosol 215219: - aersrcsoaa - Source/gain of anthropogenic secondary organic aerosol 215220: - aerddpsoaa - Dry deposition of anthropogenic secondary organic aerosol 215221: - aersdmsoaa - Sedimentation of anthropogenic secondary organic aerosol 215222: - aerwdlsoaa - Wet deposition of anthropogenic secondary organic aerosol by large-scale precipitation 215223: - aerwdcsoaa - Wet deposition of anthropogenic secondary organic aerosol by convective precipitation 215224: - aerngtsoaa - Negative fixer of anthropogenic secondary organic aerosol 215225: - aermsssoaa - Vertically integrated mass of anthropogenic secondary organic aerosol 215226: - soaod550 - Secondary organic aerosol optical depth at 550 nm 216001: - _param_216001 - Experimental product 216002: - _param_216002 - Experimental product 216003: - _param_216003 - Experimental product 216004: - _param_216004 - Experimental product 216005: - _param_216005 - Experimental product 216006: - _param_216006 - Experimental product 216007: - _param_216007 - Experimental product 216008: - _param_216008 - Experimental product 216009: - _param_216009 - Experimental product 216010: - _param_216010 - Experimental product 216011: - _param_216011 - Experimental product 216012: - _param_216012 - Experimental product 216013: - _param_216013 - Experimental product 216014: - _param_216014 - Experimental product 216015: - _param_216015 - Experimental product 216016: - _param_216016 - Experimental product 216017: - _param_216017 - Experimental product 216018: - _param_216018 - Experimental product 216019: - _param_216019 - Experimental product 216020: - _param_216020 - Experimental product 216021: - _param_216021 - Experimental product 216022: - _param_216022 - Experimental product 216023: - _param_216023 - Experimental product 216024: - _param_216024 - Experimental product 216025: - _param_216025 - Experimental product 216026: - _param_216026 - Experimental product 216027: - _param_216027 - Experimental product 216028: - _param_216028 - Experimental product 216029: - _param_216029 - Experimental product 216030: - _param_216030 - Experimental product 216031: - _param_216031 - Experimental product 216032: - _param_216032 - Experimental product 216033: - _param_216033 - Experimental product 216034: - _param_216034 - Experimental product 216035: - _param_216035 - Experimental product 216036: - _param_216036 - Experimental product 216037: - _param_216037 - Experimental product 216038: - _param_216038 - Experimental product 216039: - _param_216039 - Experimental product 216040: - _param_216040 - Experimental product 216041: - _param_216041 - Experimental product 216042: - _param_216042 - Experimental product 216043: - _param_216043 - Experimental product 216044: - _param_216044 - Experimental product 216045: - _param_216045 - Experimental product 216046: - _param_216046 - Experimental product 216047: - _param_216047 - Experimental product 216048: - _param_216048 - Experimental product 216049: - _param_216049 - Experimental product 216050: - _param_216050 - Experimental product 216051: - _param_216051 - Experimental product 216052: - _param_216052 - Experimental product 216053: - _param_216053 - Experimental product 216054: - _param_216054 - Experimental product 216055: - _param_216055 - Experimental product 216056: - _param_216056 - Experimental product 216057: - _param_216057 - Experimental product 216058: - _param_216058 - Experimental product 216059: - _param_216059 - Experimental product 216060: - _param_216060 - Experimental product 216061: - _param_216061 - Experimental product 216062: - _param_216062 - Experimental product 216063: - _param_216063 - Experimental product 216064: - _param_216064 - Experimental product 216065: - _param_216065 - Experimental product 216066: - _param_216066 - Experimental product 216067: - _param_216067 - Experimental product 216068: - _param_216068 - Experimental product 216069: - _param_216069 - Experimental product 216070: - _param_216070 - Experimental product 216071: - _param_216071 - Experimental product 216072: - _param_216072 - Experimental product 216073: - _param_216073 - Experimental product 216074: - _param_216074 - Experimental product 216075: - _param_216075 - Experimental product 216076: - _param_216076 - Experimental product 216077: - _param_216077 - Experimental product 216078: - _param_216078 - Experimental product 216079: - _param_216079 - Experimental product 216080: - _param_216080 - Experimental product 216081: - _param_216081 - Experimental product 216082: - _param_216082 - Experimental product 216083: - _param_216083 - Experimental product 216084: - _param_216084 - Experimental product 216085: - _param_216085 - Experimental product 216086: - _param_216086 - Experimental product 216087: - _param_216087 - Experimental product 216088: - _param_216088 - Experimental product 216089: - _param_216089 - Experimental product 216090: - _param_216090 - Experimental product 216091: - _param_216091 - Experimental product 216092: - _param_216092 - Experimental product 216093: - _param_216093 - Experimental product 216094: - _param_216094 - Experimental product 216095: - _param_216095 - Experimental product 216096: - _param_216096 - Experimental product 216097: - _param_216097 - Experimental product 216098: - _param_216098 - Experimental product 216099: - _param_216099 - Experimental product 216100: - _param_216100 - Experimental product 216101: - _param_216101 - Experimental product 216102: - _param_216102 - Experimental product 216103: - _param_216103 - Experimental product 216104: - _param_216104 - Experimental product 216105: - _param_216105 - Experimental product 216106: - _param_216106 - Experimental product 216107: - _param_216107 - Experimental product 216108: - _param_216108 - Experimental product 216109: - _param_216109 - Experimental product 216110: - _param_216110 - Experimental product 216111: - _param_216111 - Experimental product 216112: - _param_216112 - Experimental product 216113: - _param_216113 - Experimental product 216114: - _param_216114 - Experimental product 216115: - _param_216115 - Experimental product 216116: - _param_216116 - Experimental product 216117: - _param_216117 - Experimental product 216118: - _param_216118 - Experimental product 216119: - _param_216119 - Experimental product 216120: - _param_216120 - Experimental product 216121: - _param_216121 - Experimental product 216122: - _param_216122 - Experimental product 216123: - _param_216123 - Experimental product 216124: - _param_216124 - Experimental product 216125: - _param_216125 - Experimental product 216126: - _param_216126 - Experimental product 216127: - _param_216127 - Experimental product 216128: - _param_216128 - Experimental product 216129: - _param_216129 - Experimental product 216130: - _param_216130 - Experimental product 216131: - _param_216131 - Experimental product 216132: - _param_216132 - Experimental product 216133: - _param_216133 - Experimental product 216134: - _param_216134 - Experimental product 216135: - _param_216135 - Experimental product 216136: - _param_216136 - Experimental product 216137: - _param_216137 - Experimental product 216138: - _param_216138 - Experimental product 216139: - _param_216139 - Experimental product 216140: - _param_216140 - Experimental product 216141: - _param_216141 - Experimental product 216142: - _param_216142 - Experimental product 216143: - _param_216143 - Experimental product 216144: - _param_216144 - Experimental product 216145: - _param_216145 - Experimental product 216146: - _param_216146 - Experimental product 216147: - _param_216147 - Experimental product 216148: - _param_216148 - Experimental product 216149: - _param_216149 - Experimental product 216150: - _param_216150 - Experimental product 216151: - _param_216151 - Experimental product 216152: - _param_216152 - Experimental product 216153: - _param_216153 - Experimental product 216154: - _param_216154 - Experimental product 216155: - _param_216155 - Experimental product 216156: - _param_216156 - Experimental product 216157: - _param_216157 - Experimental product 216158: - _param_216158 - Experimental product 216159: - _param_216159 - Experimental product 216160: - _param_216160 - Experimental product 216161: - _param_216161 - Experimental product 216162: - _param_216162 - Experimental product 216163: - _param_216163 - Experimental product 216164: - _param_216164 - Experimental product 216165: - _param_216165 - Experimental product 216166: - _param_216166 - Experimental product 216167: - _param_216167 - Experimental product 216168: - _param_216168 - Experimental product 216169: - _param_216169 - Experimental product 216170: - _param_216170 - Experimental product 216171: - _param_216171 - Experimental product 216172: - _param_216172 - Experimental product 216173: - _param_216173 - Experimental product 216174: - _param_216174 - Experimental product 216175: - _param_216175 - Experimental product 216176: - _param_216176 - Experimental product 216177: - _param_216177 - Experimental product 216178: - _param_216178 - Experimental product 216179: - _param_216179 - Experimental product 216180: - _param_216180 - Experimental product 216181: - _param_216181 - Experimental product 216182: - _param_216182 - Experimental product 216183: - _param_216183 - Experimental product 216184: - _param_216184 - Experimental product 216185: - _param_216185 - Experimental product 216186: - _param_216186 - Experimental product 216187: - _param_216187 - Experimental product 216188: - _param_216188 - Experimental product 216189: - _param_216189 - Experimental product 216190: - _param_216190 - Experimental product 216191: - _param_216191 - Experimental product 216192: - _param_216192 - Experimental product 216193: - _param_216193 - Experimental product 216194: - _param_216194 - Experimental product 216195: - _param_216195 - Experimental product 216196: - _param_216196 - Experimental product 216197: - _param_216197 - Experimental product 216198: - _param_216198 - Experimental product 216199: - _param_216199 - Experimental product 216200: - _param_216200 - Experimental product 216201: - _param_216201 - Experimental product 216202: - _param_216202 - Experimental product 216203: - _param_216203 - Experimental product 216204: - _param_216204 - Experimental product 216205: - _param_216205 - Experimental product 216206: - _param_216206 - Experimental product 216207: - _param_216207 - Experimental product 216208: - _param_216208 - Experimental product 216209: - _param_216209 - Experimental product 216210: - _param_216210 - Experimental product 216211: - _param_216211 - Experimental product 216212: - _param_216212 - Experimental product 216213: - _param_216213 - Experimental product 216214: - _param_216214 - Experimental product 216215: - _param_216215 - Experimental product 216216: - _param_216216 - Experimental product 216217: - _param_216217 - Experimental product 216218: - _param_216218 - Experimental product 216219: - _param_216219 - Experimental product 216220: - _param_216220 - Experimental product 216221: - _param_216221 - Experimental product 216222: - _param_216222 - Experimental product 216223: - _param_216223 - Experimental product 216224: - _param_216224 - Experimental product 216225: - _param_216225 - Experimental product 216226: - _param_216226 - Experimental product 216227: - _param_216227 - Experimental product 216228: - _param_216228 - Experimental product 216229: - _param_216229 - Experimental product 216230: - _param_216230 - Experimental product 216231: - _param_216231 - Experimental product 216232: - _param_216232 - Experimental product 216233: - _param_216233 - Experimental product 216234: - _param_216234 - Experimental product 216235: - _param_216235 - Experimental product 216236: - _param_216236 - Experimental product 216237: - _param_216237 - Experimental product 216238: - _param_216238 - Experimental product 216239: - _param_216239 - Experimental product 216240: - _param_216240 - Experimental product 216241: - _param_216241 - Experimental product 216242: - _param_216242 - Experimental product 216243: - _param_216243 - Experimental product 216244: - _param_216244 - Experimental product 216245: - _param_216245 - Experimental product 216246: - _param_216246 - Experimental product 216247: - _param_216247 - Experimental product 216248: - _param_216248 - Experimental product 216249: - _param_216249 - Experimental product 216250: - _param_216250 - Experimental product 216251: - _param_216251 - Experimental product 216252: - _param_216252 - Experimental product 216253: - _param_216253 - Experimental product 216254: - _param_216254 - Experimental product 216255: - _param_216255 - Experimental product 217003: - h2o2 - Hydrogen peroxide 217004: - ch4_c - Methane (chemistry) 217006: - hno3 - Nitric acid 217007: - ch3ooh - Methyl peroxide 217009: - par - Paraffins 217010: - c2h4 - Ethene 217011: - ole - Olefins 217012: - ald2 - Aldehydes 217013: - pan - Peroxyacetyl nitrate 217014: - rooh - Peroxides 217015: - onit - Organic nitrates 217016: - c5h8 - Isoprene 217018: - dms - Dimethyl sulfide 217019: - nh3 - Ammonia mass mixing ratio 217020: - so4 - Sulfate 217021: - nh4 - Ammonium 217022: - msa - Methane sulfonic acid 217023: - ch3cocho - Methyl glyoxal 217024: - o3s - Stratospheric ozone 217026: - pb - Lead 217027: - 'no' - Nitrogen monoxide mass mixing ratio 217028: - ho2 - Hydroperoxy radical 217029: - ch3o2 - Methylperoxy radical 217030: - oh - Hydroxyl radical 217032: - no3 - Nitrate radical 217033: - n2o5 - Dinitrogen pentoxide 217034: - ho2no2 - Pernitric acid 217035: - c2o3 - Peroxy acetyl radical 217036: - ror - Organic ethers 217037: - rxpar - PAR budget corrector 217038: - xo2 - NO to NO2 operator 217039: - xo2n - NO to alkyl nitrate operator 217040: - nh2 - Amine 217041: - psc - Polar stratospheric cloud 217042: - ch3oh - Methanol 217043: - hcooh - Formic acid 217044: - mcooh - Methacrylic acid 217045: - c2h6 - Ethane 217046: - c2h5oh - Ethanol 217047: - c3h8 - Propane 217048: - c3h6 - Propene 217049: - c10h16 - Terpenes 217050: - ispd - Methacrolein MVK 217051: - no3_a - Nitrate 217052: - ch3coch3 - Acetone 217053: - aco2 - Acetone product 217054: - ic3h7o2 217055: - hypropo2 217056: - noxa - Nitrogen oxides Transp 217057: - co2_c - Carbon dioxide (chemistry) 217058: - n2o_c - Nitrous oxide (chemistry) 217059: - h2o - Water vapour (chemistry) 217060: - o2 - Oxygen 217061: - o2_1s - Singlet oxygen 217062: - o2_1d - Singlet delta oxygen 217063: - oclo - Chlorine dioxide 217064: - clono2 - Chlorine nitrate 217065: - hocl - Hypochlorous acid 217066: - cl2 - Chlorine 217067: - clno2 - Nitryl chloride 217068: - hbr - Hydrogen bromide 217069: - cl2o2 - Dichlorine dioxide 217070: - hobr - Hypobromous acid 217071: - cfc11 - Trichlorofluoromethane 217072: - cfc12 - Dichlorodifluoromethane 217073: - cfc113 - Trichlorotrifluoroethane 217074: - cfc114 - Dichlorotetrafluoroethane 217075: - cfc115 - Chloropentafluoroethane 217076: - ccl4 - Tetrachloromethane 217077: - ch3ccl3 - Methyl chloroform 217078: - ch3cl - Methyl chloride 217079: - hcfc22 - Chlorodifluoromethane 217080: - ch3br - Methyl bromide 217081: - ha1202 - Dibromodifluoromethane 217082: - ha1211 - Bromochlorodifluoromethane 217083: - ha1301 - Trifluorobromomethane 217084: - ha2402 - Cbrf2cbrf2 217085: - h2so4 - Sulfuric acid 217086: - hono - Nitrous acid 217087: - hc3 - Alkanes low oh rate 217088: - hc5 - Alkanes med oh rate 217089: - hc8 - Alkanes high oh rate 217090: - olt - Terminal alkenes 217091: - oli - Internal alkenes 217092: - c2h5o2 - Ethylperoxy radical 217093: - dien - Butadiene 217094: - c2h5ooh - Ethyl hydroperoxide 217095: - api - A-pinene cyclic terpenes 217096: - ch3cooh - Acetic acid 217097: - lim - D-limonene cyclic diene 217098: - ch3cho - Acetaldehyde 217099: - tol - Toluene and less reactive aromatics 217100: - xyl - Xylene and more reactive aromatics 217101: - glyald - Glycolaldehyde 217102: - cresol 217103: - ald - Acetaldehyde and higher 217104: - ch3coooh - Peracetic acid 217105: - ket - Ketones 217106: - eo2 - Hoch2ch2o2 217107: - glyoxal 217108: - eo - Hoch2ch2o 217109: - dcb - Unsaturated dicarbonyls 217110: - macr - Methacrolein 217111: - udd - Unsaturated hydroxy dicarbonyl 217112: - c3h7o2 - Isopropyldioxidanyl 217113: - hket - Hydroxy ketone 217114: - c3h7ooh - Isopropyl hydroperoxide 217115: - po2 - C3h6oho2 217116: - pooh - C3h6ohooh 217117: - op2 - Higher organic peroxides 217118: - hyac - Hydroxyacetone 217119: - paa - Peroxyacetic acid 217120: - ro2 - Ch3coch2o2 217121: - ethp - Peroxy radical from c2h6 217122: - hc3p - Peroxy radical from hc3 217123: - hc5p - Peroxy radical from hc5 217124: - bigene - Lumped alkenes 217125: - hc8p - Peroxy radical from hc8 217126: - bigalk - Lumped alkanes 217127: - etep - Peroxy radical from c2h4 217128: - mek - C4h8o 217129: - oltp - Peroxy radical from terminal alkenes 217130: - eneo2 - C4h9o3 217131: - olip - Peroxy radical from internal alkenes 217132: - meko2 - Ch3coch(oo)ch3 217133: - isopo2 - Peroxy radical from c5h8 217134: - mekooh - Ch3coch(ooh)ch3 217135: - apip - Peroxy radical from a-pinene cyclic terpenes 217136: - mco3 - Ch2=c(ch3)co3 217137: - limp - Peroxy radical from d-limonene cyclic diene 217138: - mvk - Methylvinylketone 217139: - pho - Phenoxy radical 217140: - tolp - Peroxy radical from toluene and less reactive aromatics 217141: - macro2 - Ch3c(o)ch(oo)ch2oh 217142: - xylp - Peroxy radical from xylene and more reactive aromatics 217143: - macrooh - H3c(o)ch(ooh)ch2oh 217144: - cslp - Peroxy radical from cresol 217145: - mpan - Unsaturated pans 217146: - tco3_c - Unsaturated acyl peroxy radical 217147: - ketp - Peroxy radical from ketones 217148: - alko2 - C5h11o2 217149: - olnn - No3-alkenes adduct reacting to form carbonitrates 217150: - alkooh - C5h11ooh 217151: - olnd - No3-alkenes adduct reacting via decomposition 217152: - bigald - Hoch2c(ch3)=chcho 217153: - hydrald - C5h6o2 217154: - sulf - Trop sulfuric acid 217155: - ox - Oxides 217156: - isopno3 - Ch2chc(ch3)(oo)ch2ono2 217157: - onitr - C3 organic nitrate 217158: - clox - Chlorine oxides 217159: - brox - Bromine oxides 217160: - xooh - Hoch2c(ooh)(ch3)chchoh 217161: - isopooh - Hoch2c(ooh)(ch3)ch=ch2 217162: - toluene - Lumped aromatics 217163: - dmso - Dimethyl sulfoxyde 217164: - tolo2 - C7h9o5 217165: - tolooh - C7h10o5 217166: - h2s - Hydrogensulfide 217167: - xoh - C7h10o6 217168: - noy - All nitrogen oxides 217169: - cly - Chlorine family 217170: - terpo2 - C10h16(oh)(oo) 217171: - bry - Bromine family 217172: - terpooh - C10h18o3 217173: - n - Nitrogen atom 217174: - clo - Chlorine monoxide 217175: - cl_c - Chlorine atom 217176: - bro - Bromine monoxide 217177: - h_c - Hydrogen atom 217178: - ch3 - Methyl group 217179: - addt - Aromatic-ho from toluene and less reactive aromatics 217180: - addx - Aromatic-ho from xylene and more reactive aromatics 217181: - nh4no3 - Ammonium nitrate 217182: - addc - Aromatic-ho from csl 217183: - soa1 - Secondary organic aerosol type 1 217184: - soa2a - Secondary organic aerosol type 2a 217185: - soa2b - Secondary organic aerosol type 2b 217186: - sog1 - Condensable gas type 1 217187: - sog2a - Condensable gas type 2a 217188: - sog2b - Condensable gas type 2b 217189: - so3 - Sulfur trioxide 217190: - ocs_c - Carbonyl sulfide 217191: - br - Bromine atom 217192: - br2 - Bromine 217193: - brcl - Bromine monochloride 217194: - brono2 - Bromine nitrate 217195: - ch2br2 - Dibromomethane 217196: - ch3o - Methoxy radical 217197: - chbr3 - Tribromomethane 217198: - cloo - Asymmetric chlorine dioxide radical 217199: - h2 - Hydrogen 217200: - hcl - Hydrogen chloride 217201: - hco - Formyl radical 217202: - hf - Hydrogen fluoride 217203: - o - Oxygen atom 217204: - o1d - Excited oxygen atom 217205: - o3p - Ground state oxygen atom 217206: - strataer - Stratospheric aerosol 217222: - aroo2 - Aromatic peroxy radical mass mixing ratio 217223: - c2h2 - Ethyne mass mixing ratio 217224: - ch3cn - Acetonitrile mass mixing ratio 217225: - ch3o2no2 - Methyl peroxy nitrate mass mixing ratio 217226: - hcn - Hydrogen cyanide mass mixing ratio 217227: - hpald1 - Hydroperoxy aldehydes type 1 mass mixing ratio 217228: - hpald - Hydroperoxy aldehydes type 2 mass mixing ratio 217229: - isopbo2 - Isoprene peroxy type B mass mixing ratio 217230: - isopdo2 - Isoprene peroxy type D mass mixing ratio 217231: - voca - Anthropogenic volatile organic compounds mass mixing ratio 217232: - vocbb - Biomass burning volatile organic compounds mass mixing ratio 218003: - tc_h2o2 - Total column hydrogen peroxide 218004: - tc_ch4 - Total column methane 218006: - tc_hno3 - Total column nitric acid 218007: - tc_ch3ooh - Total column methyl peroxide 218009: - tc_par - Total column paraffins 218010: - tc_c2h4 - Total column ethene 218011: - tc_ole - Total column olefins 218012: - tc_ald2 - Total column aldehydes 218013: - tc_pan - Total column peroxyacetyl nitrate 218014: - tc_rooh - Total column peroxides 218015: - tc_onit - Total column organic nitrates 218016: - tc_c5h8 - Total column isoprene 218018: - tc_dms - Total column dimethyl sulfide 218019: - tc_nh3 - Total column ammonia 218020: - tc_so4 - Total column sulfate 218021: - tc_nh4 - Total column ammonium 218022: - tc_msa - Total column methane sulfonic acid 218023: - tc_ch3cocho - Total column methyl glyoxal 218024: - tc_o3s - Total column stratospheric ozone 218026: - tc_pb - Total column lead 218027: - tc_no - Total column nitrogen monoxide 218028: - tc_ho2 - Total column hydroperoxy radical 218029: - tc_ch3o2 - Total column methylperoxy radical 218030: - tc_oh - Total column hydroxyl radical 218032: - tc_no3 - Total column nitrate radical 218033: - tc_n2o5 - Total column dinitrogen pentoxide 218034: - tc_ho2no2 - Total column pernitric acid 218035: - tc_c2o3 - Total column peroxy acetyl radical 218036: - tc_ror - Total column organic ethers 218037: - tc_rxpar - Total column PAR budget corrector 218038: - tc_xo2 - Total column NO to NO2 operator 218039: - tc_xo2n - Total column NO to alkyl nitrate operator 218040: - tc_nh2 - Total column amine 218041: - tc_psc - Total column polar stratospheric cloud 218042: - tc_ch3oh - Total column methanol 218043: - tc_hcooh - Total column formic acid 218044: - tc_mcooh - Total column methacrylic acid 218045: - tc_c2h6 - Total column ethane 218046: - tc_c2h5oh - Total column ethanol 218047: - tc_c3h8 - Total column propane 218048: - tc_c3h6 - Total column propene 218049: - tc_c10h16 - Total column terpenes 218050: - tc_ispd - Total column methacrolein MVK 218051: - tc_no3_a - Total column nitrate 218052: - tc_ch3coch3 - Total column acetone 218053: - tc_aco2 - Total column acetone product 218054: - tc_ic3h7o2 - Total column IC3H7O2 218055: - tc_hypropo2 - Total column HYPROPO2 218056: - tc_noxa - Total column nitrogen oxides Transp 218057: - tc_co2_c - Total column of carbon dioxide (chemistry) 218058: - tc_n2o_c - Total column of nitrous oxide (chemistry) 218059: - tc_h2o - Total column of water vapour (chemistry) 218060: - tc_o2 - Total column of oxygen 218061: - tc_o2_1s - Total column of singlet oxygen 218062: - tc_o2_1d - Total column of singlet delta oxygen 218063: - tc_oclo - Total column of chlorine dioxide 218064: - tc_clono2 - Total column of chlorine nitrate 218065: - tc_hocl - Total column of hypochlorous acid 218066: - tc_cl2 - Total column of chlorine 218067: - tc_clno2 - Total column of nitryl chloride 218068: - tc_hbr - Total column of hydrogen bromide 218069: - tc_cl2o2 - Total column of dichlorine dioxide 218070: - tc_hobr - Total column of hypobromous acid 218071: - tc_cfc11 - Total column of trichlorofluoromethane 218072: - tc_cfc12 - Total column of dichlorodifluoromethane 218073: - tc_cfc113 - Total column of trichlorotrifluoroethane 218074: - tc_cfc114 - Total column of dichlorotetrafluoroethane 218075: - tc_cfc115 - Total column of chloropentafluoroethane 218076: - tc_ccl4 - Total column of tetrachloromethane 218077: - tc_ch3ccl3 - Total column of methyl chloroform 218078: - tc_ch3cl - Total column of methyl chloride 218079: - tc_hcfc22 - Total column of chlorodifluoromethane 218080: - tc_ch3br - Total column of methyl bromide 218081: - tc_ha1202 - Total column of dibromodifluoromethane 218082: - tc_ha1211 - Total column of bromochlorodifluoromethane 218083: - tc_ha1301 - Total column of trifluorobromomethane 218084: - tc_ha2402 - Total column of cbrf2cbrf2 218085: - tc_h2so4 - Total column of sulfuric acid 218086: - tc_hono - Total column of nitrous acid 218087: - tc_hc3 - Total column of alkanes low oh rate 218088: - tc_hc5 - Total column of alkanes med oh rate 218089: - tc_hc8 - Total column of alkanes high oh rate 218090: - tc_olt - Total column of terminal alkenes 218091: - tc_oli - Total column of internal alkenes 218092: - tc_c2h5o2 - Total column of ethylperoxy radical 218093: - tc_dien - Total column of butadiene 218094: - tc_c2h5ooh - Total column of ethyl hydroperoxide 218095: - tc_api - Total column of a-pinene cyclic terpenes 218096: - tc_ch3cooh - Total column of acetic acid 218097: - tc_lim - Total column of d-limonene cyclic diene 218098: - tc_ch3cho - Total column of acetaldehyde 218099: - tc_tol - Total column of toluene and less reactive aromatics 218100: - tc_xyl - Total column of xylene and more reactive aromatics 218101: - tc_glyald - Total column of glycolaldehyde 218102: - tc_cresol - Total column of cresol 218103: - tc_ald - Total column of acetaldehyde and higher 218104: - tc_ch3coooh - Total column of peracetic acid 218105: - tc_ket - Total column of ketones 218106: - tc_eo2 - Total column of hoch2ch2o2 218107: - tc_glyoxal - Total column of glyoxal 218108: - tc_eo - Total column of hoch2ch2o 218109: - tc_dcb - Total column of unsaturated dicarbonyls 218110: - tc_macr - Total column of methacrolein 218111: - tc_udd - Total column of unsaturated hydroxy dicarbonyl 218112: - tc_c3h7o2 - Total column of isopropyldioxidanyl 218113: - tc_hket - Total column of hydroxy ketone 218114: - tc_c3h7ooh - Total column of isopropyl hydroperoxide 218115: - tc_po2 - Total column of c3h6oho2 218116: - tc_pooh - Total column of c3h6ohooh 218117: - tc_op2 - Total column of higher organic peroxides 218118: - tc_hyac - Total column of hydroxyacetone 218119: - tc_paa - Total column of peroxyacetic acid 218120: - tc_ro2 - Total column of ch3coch2o2 218121: - tc_ethp - Total column of peroxy radical from c2h6 218122: - tc_hc3p - Total column of peroxy radical from hc3 218123: - tc_hc5p - Total column of peroxy radical from hc5 218124: - tc_bigene - Total column of lumped alkenes 218125: - tc_hc8p - Total column of peroxy radical from hc8 218126: - tc_bigalk - Total column of lumped alkanes 218127: - tc_etep - Total column of peroxy radical from c2h4 218128: - tc_mek - Total column of c4h8o 218129: - tc_oltp - Total column of peroxy radical from terminal alkenes 218130: - tc_eneo2 - Total column of c4h9o3 218131: - tc_olip - Total column of peroxy radical from internal alkenes 218132: - tc_meko2 - Total column of ch3coch(oo)ch3 218133: - tc_isopo2 - Total column of peroxy radical from c5h8 218134: - tc_mekooh - Total column of ch3coch(ooh)ch3 218135: - tc_apip - Total column of peroxy radical from a-pinene cyclic terpenes 218136: - tc_mco3 - Total column of ch2=c(ch3)co3 218137: - tc_limp - Total column of peroxy radical from d-limonene cyclic diene 218138: - tc_mvk - Total column of methylvinylketone 218139: - tc_pho - Total column of phenoxy radical 218140: - tc_tolp - Total column of peroxy radical from toluene and less reactive aromatics 218141: - tc_macro2 - Total column of ch3c(o)ch(oo)ch2oh 218142: - tc_xylp - Total column of peroxy radical from xylene and more reactive aromatics 218143: - tc_macrooh - Total column of h3c(o)ch(ooh)ch2oh 218144: - tc_cslp - Total column of peroxy radical from cresol 218145: - tc_mpan - Total column of unsaturated pans 218146: - tc_tco3_c - Total column of unsaturated acyl peroxy radical 218147: - tc_ketp - Total column of peroxy radical from ketones 218148: - tc_alko2 - Total column of c5h11o2 218149: - tc_olnn - Total column of no3-alkenes adduct reacting to form carbonitrates 218150: - tc_alkooh - Total column of c5h11ooh 218151: - tc_olnd - Total column of no3-alkenes adduct reacting via decomposition 218152: - tc_bigald - Total column of hoch2c(ch3)=chcho 218153: - tc_hydrald - Total column of c5h6o2 218154: - tc_sulf - Total column of trop sulfuric acid 218155: - tc_ox - Total column of oxides 218156: - tc_isopno3 - Total column of ch2chc(ch3)(oo)ch2ono2 218157: - tc_onitr - Total column of c3 organic nitrate 218158: - tc_clox - Total column of chlorine oxides 218159: - tc_brox - Total column of bromine oxides 218160: - tc_xooh - Total column of hoch2c(ooh)(ch3)chchoh 218161: - tc_isopooh - Total column of hoch2c(ooh)(ch3)ch=ch2 218162: - tc_toluene - Total column of lumped aromatics 218163: - tc_dmso - Total column of dimethyl sulfoxyde 218164: - tc_tolo2 - Total column of c7h9o5 218165: - tc_tolooh - Total column of c7h10o5 218166: - tc_h2s - Total column of hydrogensulfide 218167: - tc_xoh - Total column of c7h10o6 218168: - tc_noy - Total column of all nitrogen oxides 218169: - tc_cly - Total column of chlorine family 218170: - tc_terpo2 - Total column of c10h16(oh)(oo) 218171: - tc_bry - Total column of bromine family 218172: - tc_terpooh - Total column of c10h18o3 218173: - tc_n - Total column of nitrogen atom 218174: - tc_clo - Total column of chlorine monoxide 218175: - tc_cl_c - Total column of chlorine atom 218176: - tc_bro - Total column of bromine monoxide 218177: - tc_h_c - Total column of hydrogen atom 218178: - tc_ch3 - Total column of methyl group 218179: - tc_addt - Total column of aromatic-ho from toluene and less reactive aromatics 218180: - tc_addx - Total column of aromatic-ho from xylene and more reactive aromatics 218181: - tc_nh4no3 - Total column of ammonium nitrate 218182: - tc_addc - Total column of aromatic-ho from csl 218183: - tc_soa1 - Total column of secondary organic aerosol type 1 218184: - tc_soa2a - Total column of secondary organic aerosol type 2a 218185: - tc_soa2b - Total column of secondary organic aerosol type 2b 218186: - tc_sog1 - Total column of condensable gas type 1 218187: - tc_sog2a - Total column of condensable gas type 2a 218188: - tc_sog2b - Total column of condensable gas type 2b 218189: - tc_so3 - Total column of sulfur trioxide 218190: - tc_ocs_c - Total column of carbonyl sulfide 218191: - tc_br - Total column of bromine atom 218192: - tc_br2 - Total column of bromine 218193: - tc_brcl - Total column of bromine monochloride 218194: - tc_brono2 - Total column of bromine nitrate 218195: - tc_ch2br2 - Total column of dibromomethane 218196: - tc_ch3o - Total column of methoxy radical 218197: - tc_chbr3 - Total column of tribromomethane 218198: - tc_cloo - Total column of asymmetric chlorine dioxide radical 218199: - tc_h2 - Total column of hydrogen 218200: - tc_hcl - Total column of hydrogen chloride 218201: - tc_hco - Total column of formyl radical 218202: - tc_hf - Total column of hydrogen fluoride 218203: - tc_o - Total column of oxygen atom 218204: - tc_o1d - Total column of excited oxygen atom 218205: - tc_o3p - Total column of ground state oxygen atom 218206: - tc_strataer - Total column of stratospheric aerosol 218221: - tc_vso2 - Column integrated mass density of Volcanic sulfur dioxide 218222: - tc_aroo2 - Column integrated mass density of Aromatic peroxy radical 218223: - tc_c2h2 - Column integrated mass density of Ethyne 218224: - tc_ch3cn - Column integrated mass density of Acetonitrile 218225: - tc_ch3o2no2 - Column integrated mass density of Methyl peroxy nitrate 218226: - tc_hcn - Column integrated mass density of Hydrogen cyanide 218227: - tc_hpald1 - Column integrated mass density of Hydroperoxy aldehydes type 1 218228: - tc_hpald2 - Column integrated mass density of Hydroperoxy aldehydes type 2 218229: - tc_isopbo2 - Column integrated mass density of Isoprene peroxy type B 218230: - tc_isopdo2 - Column integrated mass density of Isoprene peroxy type D 218231: - tc_voca - Column integrated mass density of Anthropogenic volatile organic compounds 218232: - tc_vocbb - Column integrated mass density of Biomass burning volatile organic compounds 219001: - e_go3 - Ozone emissions 219002: - e_nox - Nitrogen oxides emissions 219003: - e_h2o2 - Hydrogen peroxide emissions 219004: - e_ch4 - Methane emissions 219005: - e_co - Carbon monoxide emissions 219006: - e_hno3 - Nitric acid emissions 219007: - e_ch3ooh - Methyl peroxide emissions 219008: - e_hcho - Formaldehyde emissions 219009: - e_par - Paraffins emissions 219010: - e_c2h4 - Ethene emissions 219011: - e_ole - Olefins emissions 219012: - e_ald2 - Aldehydes emissions 219013: - e_pan - Peroxyacetyl nitrate emissions 219014: - e_rooh - Peroxides emissions 219015: - e_onit - Organic nitrates emissions 219016: - e_c5h8 - Isoprene emissions 219017: - e_so2 - Sulfur dioxide emissions 219018: - e_dms - Dimethyl sulfide emissions 219019: - e_nh3 - Ammonia emissions 219020: - e_so4 - Sulfate emissions 219021: - e_nh4 - Ammonium emissions 219022: - e_msa - Methane sulfonic acid emissions 219023: - e_ch3cocho - Methyl glyoxal emissions 219024: - e_o3s - Stratospheric ozone emissions 219025: - e_ra - Radon emissions 219026: - e_pb - Lead emissions 219027: - e_no - Nitrogen monoxide emissions 219028: - e_ho2 - Hydroperoxy radical emissions 219029: - e_ch3o2 - Methylperoxy radical emissions 219030: - e_oh - Hydroxyl radical emissions 219031: - e_no2 - Nitrogen dioxide emissions 219032: - e_no3 - Nitrate radical emissions 219033: - e_n2o5 - Dinitrogen pentoxide emissions 219034: - e_ho2no2 - Pernitric acid emissions 219035: - e_c2o3 - Peroxy acetyl radical emissions 219036: - e_ror - Organic ethers emissions 219037: - e_rxpar - PAR budget corrector emissions 219038: - e_xo2 - NO to NO2 operator emissions 219039: - e_xo2n - NO to alkyl nitrate operator emissions 219040: - e_nh2 - Amine emissions 219041: - e_psc - Polar stratospheric cloud emissions 219042: - e_ch3oh - Methanol emissions 219043: - e_hcooh - Formic acid emissions 219044: - e_mcooh - Methacrylic acid emissions 219045: - e_c2h6 - Ethane emissions 219046: - e_c2h5oh - Ethanol emissions 219047: - e_c3h8 - Propane emissions 219048: - e_c3h6 - Propene emissions 219049: - e_c10h16 - Terpenes emissions 219050: - e_ispd - Methacrolein MVK emissions 219051: - e_no3_a - Nitrate emissions 219052: - e_ch3coch3 - Acetone emissions 219053: - e_aco2 - Acetone product emissions 219054: - e_ic3h7o2 - IC3H7O2 emissions 219055: - e_hypropo2 - HYPROPO2 emissions 219056: - e_noxa - Nitrogen oxides Transp emissions 219057: - e_co2_c - Emissions of carbon dioxide (chemistry) 219058: - e_n2o_c - Emissions of nitrous oxide (chemistry) 219059: - e_h2o - Emissions of water vapour (chemistry) 219060: - e_o2 - Emissions of oxygen 219061: - e_o2_1s - Emissions of singlet oxygen 219062: - e_o2_1d - Emissions of singlet delta oxygen 219063: - e_oclo - Emissions of chlorine dioxide 219064: - e_clono2 - Emissions of chlorine nitrate 219065: - e_hocl - Emissions of hypochlorous acid 219066: - e_cl2 - Emissions of chlorine 219067: - e_clno2 - Emissions of nitryl chloride 219068: - e_hbr - Emissions of hydrogen bromide 219069: - e_cl2o2 - Emissions of dichlorine dioxide 219070: - e_hobr - Emissions of hypobromous acid 219071: - e_cfc11 - Emissions of trichlorofluoromethane 219072: - e_cfc12 - Emissions of dichlorodifluoromethane 219073: - e_cfc113 - Emissions of trichlorotrifluoroethane 219074: - e_cfc114 - Emissions of dichlorotetrafluoroethane 219075: - e_cfc115 - Emissions of chloropentafluoroethane 219076: - e_ccl4 - Emissions of tetrachloromethane 219077: - e_ch3ccl3 - Emissions of methyl chloroform 219078: - e_ch3cl - Emissions of methyl chloride 219079: - e_hcfc22 - Emissions of chlorodifluoromethane 219080: - e_ch3br - Emissions of methyl bromide 219081: - e_ha1202 - Emissions of dibromodifluoromethane 219082: - e_ha1211 - Emissions of bromochlorodifluoromethane 219083: - e_ha1301 - Emissions of trifluorobromomethane 219084: - e_ha2402 - Emissions of cbrf2cbrf2 219085: - e_h2so4 - Emissions of sulfuric acid 219086: - e_hono - Emissions of nitrous acid 219087: - e_hc3 - Emissions of alkanes low oh rate 219088: - e_hc5 - Emissions of alkanes med oh rate 219089: - e_hc8 - Emissions of alkanes high oh rate 219090: - e_olt - Emissions of terminal alkenes 219091: - e_oli - Emissions of internal alkenes 219092: - e_c2h5o2 - Emissions of ethylperoxy radical 219093: - e_dien - Emissions of butadiene 219094: - e_c2h5ooh - Emissions of ethyl hydroperoxide 219095: - e_api - Emissions of a-pinene cyclic terpenes 219096: - e_ch3cooh - Emissions of acetic acid 219097: - e_lim - Emissions of d-limonene cyclic diene 219098: - e_ch3cho - Emissions of acetaldehyde 219099: - e_tol - Emissions of toluene and less reactive aromatics 219100: - e_xyl - Emissions of xylene and more reactive aromatics 219101: - e_glyald - Emissions of glycolaldehyde 219102: - e_cresol - Emissions of cresol 219103: - e_ald - Emissions of acetaldehyde and higher 219104: - e_ch3coooh - Emissions of peracetic acid 219105: - e_ket - Emissions of ketones 219106: - e_eo2 - Emissions of hoch2ch2o2 219107: - e_glyoxal - Emissions of glyoxal 219108: - e_eo - Emissions of hoch2ch2o 219109: - e_dcb - Emissions of unsaturated dicarbonyls 219110: - e_macr - Emissions of methacrolein 219111: - e_udd - Emissions of unsaturated hydroxy dicarbonyl 219112: - e_c3h7o2 - Emissions of isopropyldioxidanyl 219113: - e_hket - Emissions of hydroxy ketone 219114: - e_c3h7ooh - Emissions of isopropyl hydroperoxide 219115: - e_po2 - Emissions of c3h6oho2 219116: - e_pooh - Emissions of c3h6ohooh 219117: - e_op2 - Emissions of higher organic peroxides 219118: - e_hyac - Emissions of hydroxyacetone 219119: - e_paa - Emissions of peroxyacetic acid 219120: - e_ro2 - Emissions of ch3coch2o2 219121: - e_ethp - Emissions of peroxy radical from c2h6 219122: - e_hc3p - Emissions of peroxy radical from hc3 219123: - e_hc5p - Emissions of peroxy radical from hc5 219124: - e_bigene - Emissions of lumped alkenes 219125: - e_hc8p - Emissions of peroxy radical from hc8 219126: - e_bigalk - Emissions of lumped alkanes 219127: - e_etep - Emissions of peroxy radical from c2h4 219128: - e_mek - Emissions of c4h8o 219129: - e_oltp - Emissions of peroxy radical from terminal alkenes 219130: - e_eneo2 - Emissions of c4h9o3 219131: - e_olip - Emissions of peroxy radical from internal alkenes 219132: - e_meko2 - Emissions of ch3coch(oo)ch3 219133: - e_isopo2 - Emissions of peroxy radical from c5h8 219134: - e_mekooh - Emissions of ch3coch(ooh)ch3 219135: - e_apip - Emissions of peroxy radical from a-pinene cyclic terpenes 219136: - e_mco3 - Emissions of ch2=c(ch3)co3 219137: - e_limp - Emissions of peroxy radical from d-limonene cyclic diene 219138: - e_mvk - Emissions of methylvinylketone 219139: - e_pho - Emissions of phenoxy radical 219140: - e_tolp - Emissions of peroxy radical from toluene and less reactive aromatics 219141: - e_macro2 - Emissions of ch3c(o)ch(oo)ch2oh 219142: - e_xylp - Emissions of peroxy radical from xylene and more reactive aromatics 219143: - e_macrooh - Emissions of h3c(o)ch(ooh)ch2oh 219144: - e_cslp - Emissions of peroxy radical from cresol 219145: - e_mpan - Emissions of unsaturated pans 219146: - e_tco3_c - Emissions of unsaturated acyl peroxy radical 219147: - e_ketp - Emissions of peroxy radical from ketones 219148: - e_alko2 - Emissions of c5h11o2 219149: - e_olnn - Emissions of no3-alkenes adduct reacting to form carbonitrates 219150: - e_alkooh - Emissions of c5h11ooh 219151: - e_olnd - Emissions of no3-alkenes adduct reacting via decomposition 219152: - e_bigald - Emissions of hoch2c(ch3)=chcho 219153: - e_hydrald - Emissions of c5h6o2 219154: - e_sulf - Emissions of trop sulfuric acid 219155: - e_ox - Emissions of oxides 219156: - e_isopno3 - Emissions of ch2chc(ch3)(oo)ch2ono2 219157: - e_onitr - Emissions of c3 organic nitrate 219158: - e_clox - Emissions of chlorine oxides 219159: - e_brox - Emissions of bromine oxides 219160: - e_xooh - Emissions of hoch2c(ooh)(ch3)chchoh 219161: - e_isopooh - Emissions of hoch2c(ooh)(ch3)ch=ch2 219162: - e_toluene - Emissions of lumped aromatics 219163: - e_dmso - Emissions of dimethyl sulfoxyde 219164: - e_tolo2 - Emissions of c7h9o5 219165: - e_tolooh - Emissions of c7h10o5 219166: - e_h2s - Emissions of hydrogensulfide 219167: - e_xoh - Emissions of c7h10o6 219168: - e_noy - Emissions of all nitrogen oxides 219169: - e_cly - Emissions of chlorine family 219170: - e_terpo2 - Emissions of c10h16(oh)(oo) 219171: - e_bry - Emissions of bromine family 219172: - e_terpooh - Emissions of c10h18o3 219173: - e_n - Emissions of nitrogen atom 219174: - e_clo - Emissions of chlorine monoxide 219175: - e_cl_c - Emissions of chlorine atom 219176: - e_bro - Emissions of bromine monoxide 219177: - e_h_c - Emissions of hydrogen atom 219178: - e_ch3 - Emissions of methyl group 219179: - e_addt - Emissions of aromatic-ho from toluene and less reactive aromatics 219180: - e_addx - Emissions of aromatic-ho from xylene and more reactive aromatics 219181: - e_nh4no3 - Emissions of ammonium nitrate 219182: - e_addc - Emissions of aromatic-ho from csl 219183: - e_soa1 - Emissions of secondary organic aerosol type 1 219184: - e_soa2a - Emissions of secondary organic aerosol type 2a 219185: - e_soa2b - Emissions of secondary organic aerosol type 2b 219186: - e_sog1 - Emissions of condensable gas type 1 219187: - e_sog2a - Emissions of condensable gas type 2a 219188: - e_sog2b - Emissions of condensable gas type 2b 219189: - e_so3 - Emissions of sulfur trioxide 219190: - e_ocs_c - Emissions of carbonyl sulfide 219191: - e_br - Emissions of bromine atom 219192: - e_br2 - Emissions of bromine 219193: - e_brcl - Emissions of bromine monochloride 219194: - e_brono2 - Emissions of bromine nitrate 219195: - e_ch2br2 - Emissions of dibromomethane 219196: - e_ch3o - Emissions of methoxy radical 219197: - e_chbr3 - Emissions of tribromomethane 219198: - e_cloo - Emissions of asymmetric chlorine dioxide radical 219199: - e_h2 - Emissions of hydrogen 219200: - e_hcl - Emissions of hydrogen chloride 219201: - e_hco - Emissions of formyl radical 219202: - e_hf - Emissions of hydrogen fluoride 219203: - e_o - Emissions of oxygen atom 219204: - e_o1d - Emissions of excited oxygen atom 219205: - e_o3p - Emissions of ground state oxygen atom 219206: - e_strataer - Emissions of stratospheric aerosol 219207: - parfire - Wildfire flux of paraffins 219208: - olefire - Wildfire flux of olefines 219209: - ald2fire - Wildfire flux of aldehydes 219210: - ketfire - Wildfire flux of ketones 219211: - apifire - Wildfire flux of f a-pinene cyclic terpenes 219212: - tolfire - Wildfire flux of toluene less reactive aromatics 219213: - xylfire - Wildfire flux of xylene more reactive aromatics 219214: - limfire - Wildfire flux of d-limonene cyclic diene 219215: - oltfire - Wildfire flux of terminal alkenes 219216: - hc3fire - Wildfire flux of alkanes low oh rate 219217: - hc5fire - Wildfire flux of alkanes med oh rate 219218: - hc8fire - Wildfire flux of alkanes high oh rate 219219: - hcnfire - Wildfire flux of hydrogen cyanide 219220: - ch3cnfire - Wildfire flux of acetonitrile 219221: - e_vso2 - Atmosphere emission mass flux of Volcanic sulfur dioxide 219222: - e_aroo2 - Atmosphere emission mass flux of Aromatic peroxy radical 219223: - e_c2h2 - Atmosphere emission mass flux of Ethyne 219224: - e_ch3cn - Atmosphere emission mass flux of Acetonitrile 219225: - e_ch3o2no2 - Atmosphere emission mass flux of Methyl peroxy nitrate 219226: - e_hcn - Atmosphere emission mass flux of Hydrogen cyanide 219227: - e_hpald1 - Atmosphere emission mass flux of Hydroperoxy aldehydes type 1 219228: - e_hpald2 - Atmosphere emission mass flux of Hydroperoxy aldehydes type 2 219229: - e_isopbo2 - Atmosphere emission mass flux of Isoprene peroxy type B 219230: - e_isopdo2 - Atmosphere emission mass flux of Isoprene peroxy type D 219231: - e_voca - Atmosphere emission mass flux of Anthropogenic volatile organic compounds 219232: - e_vocbb - Atmosphere emission mass flux of Biomass burning volatile organic compounds 220228: - tpoc - Total precipitation observation count 221001: - dv_go3 - Ozone deposition velocity 221002: - dv_nox - Nitrogen oxides deposition velocity 221003: - dv_h2o2 - Hydrogen peroxide deposition velocity 221004: - dv_ch4 - Methane deposition velocity 221005: - dv_co - Carbon monoxide deposition velocity 221006: - dv_hno3 - Nitric acid deposition velocity 221007: - dv_ch3ooh - Methyl peroxide deposition velocity 221008: - dv_hcho - Formaldehyde deposition velocity 221009: - dv_par - Paraffins deposition velocity 221010: - dv_c2h4 - Ethene deposition velocity 221011: - dv_ole - Olefins deposition velocity 221012: - dv_ald2 - Aldehydes deposition velocity 221013: - dv_pan - Peroxyacetyl nitrate deposition velocity 221014: - dv_rooh - Peroxides deposition velocity 221015: - dv_onit - Organic nitrates deposition velocity 221016: - dv_c5h8 - Isoprene deposition velocity 221017: - dv_so2 - Sulfur dioxide deposition velocity 221018: - dv_dms - Dimethyl sulfide deposition velocity 221019: - dv_nh3 - Ammonia deposition velocity 221020: - dv_so4 - Sulfate deposition velocity 221021: - dv_nh4 - Ammonium deposition velocity 221022: - dv_msa - Methane sulfonic acid deposition velocity 221023: - dv_ch3cocho - Methyl glyoxal deposition velocity 221024: - dv_o3s - Stratospheric ozone deposition velocity 221025: - dv_ra - Radon deposition velocity 221026: - dv_pb - Lead deposition velocity 221027: - dv_no - Nitrogen monoxide deposition velocity 221028: - dv_ho2 - Hydroperoxy radical deposition velocity 221029: - dv_ch3o2 - Methylperoxy radical deposition velocity 221030: - dv_oh - Hydroxyl radical deposition velocity 221031: - dv_no2 - Nitrogen dioxide deposition velocity 221032: - dv_no3 - Nitrate radical deposition velocity 221033: - dv_n2o5 - Dinitrogen pentoxide deposition velocity 221034: - dv_ho2no2 - Pernitric acid deposition velocity 221035: - dv_c2o3 - Peroxy acetyl radical deposition velocity 221036: - dv_ror - Organic ethers deposition velocity 221037: - dv_rxpar - PAR budget corrector deposition velocity 221038: - dv_xo2 - NO to NO2 operator deposition velocity 221039: - dv_xo2n - NO to alkyl nitrate operator deposition velocity 221040: - dv_nh2 - Amine deposition velocity 221041: - dv_psc - Polar stratospheric cloud deposition velocity 221042: - dv_ch3oh - Methanol deposition velocity 221043: - dv_hcooh - Formic acid deposition velocity 221044: - dv_mcooh - Methacrylic acid deposition velocity 221045: - dv_c2h6 - Ethane deposition velocity 221046: - dv_c2h5oh - Ethanol deposition velocity 221047: - dv_c3h8 - Propane deposition velocity 221048: - dv_c3h6 - Propene deposition velocity 221049: - dv_c10h16 - Terpenes deposition velocity 221050: - dv_ispd - Methacrolein MVK deposition velocity 221051: - dv_no3_a - Nitrate deposition velocity 221052: - dv_ch3coch3 - Acetone deposition velocity 221053: - dv_aco2 - Acetone product deposition velocity 221054: - dv_ic3h7o2 - IC3H7O2 deposition velocity 221055: - dv_hypropo2 - HYPROPO2 deposition velocity 221056: - dv_noxa - Nitrogen oxides Transp deposition velocity 221057: - dv_co2_c - Dry deposition velocity of carbon dioxide (chemistry) 221058: - dv_n2o_c - Dry deposition velocity of nitrous oxide (chemistry) 221059: - dv_h2o - Dry deposition velocity of water vapour (chemistry) 221060: - dv_o2 - Dry deposition velocity of oxygen 221061: - dv_o2_1s - Dry deposition velocity of singlet oxygen 221062: - dv_o2_1d - Dry deposition velocity of singlet delta oxygen 221063: - dv_oclo - Dry deposition velocity of chlorine dioxide 221064: - dv_clono2 - Dry deposition velocity of chlorine nitrate 221065: - dv_hocl - Dry deposition velocity of hypochlorous acid 221066: - dv_cl2 - Dry deposition velocity of chlorine 221067: - dv_clno2 - Dry deposition velocity of nitryl chloride 221068: - dv_hbr - Dry deposition velocity of hydrogen bromide 221069: - dv_cl2o2 - Dry deposition velocity of dichlorine dioxide 221070: - dv_hobr - Dry deposition velocity of hypobromous acid 221071: - dv_cfc11 - Dry deposition velocity of trichlorofluoromethane 221072: - dv_cfc12 - Dry deposition velocity of dichlorodifluoromethane 221073: - dv_cfc113 - Dry deposition velocity of trichlorotrifluoroethane 221074: - dv_cfc114 - Dry deposition velocity of dichlorotetrafluoroethane 221075: - dv_cfc115 - Dry deposition velocity of chloropentafluoroethane 221076: - dv_ccl4 - Dry deposition velocity of tetrachloromethane 221077: - dv_ch3ccl3 - Dry deposition velocity of methyl chloroform 221078: - dv_ch3cl - Dry deposition velocity of methyl chloride 221079: - dv_hcfc22 - Dry deposition velocity of chlorodifluoromethane 221080: - dv_ch3br - Dry deposition velocity of methyl bromide 221081: - dv_ha1202 - Dry deposition velocity of dibromodifluoromethane 221082: - dv_ha1211 - Dry deposition velocity of bromochlorodifluoromethane 221083: - dv_ha1301 - Dry deposition velocity of trifluorobromomethane 221084: - dv_ha2402 - Dry deposition velocity of cbrf2cbrf2 221085: - dv_h2so4 - Dry deposition velocity of sulfuric acid 221086: - dv_hono - Dry deposition velocity of nitrous acid 221087: - dv_hc3 - Dry deposition velocity of alkanes low oh rate 221088: - dv_hc5 - Dry deposition velocity of alkanes med oh rate 221089: - dv_hc8 - Dry deposition velocity of alkanes high oh rate 221090: - dv_olt - Dry deposition velocity of terminal alkenes 221091: - dv_oli - Dry deposition velocity of internal alkenes 221092: - dv_c2h5o2 - Dry deposition velocity of ethylperoxy radical 221093: - dv_dien - Dry deposition velocity of butadiene 221094: - dv_c2h5ooh - Dry deposition velocity of ethyl hydroperoxide 221095: - dv_api - Dry deposition velocity of a-pinene cyclic terpenes 221096: - dv_ch3cooh - Dry deposition velocity of acetic acid 221097: - dv_lim - Dry deposition velocity of d-limonene cyclic diene 221098: - dv_ch3cho - Dry deposition velocity of acetaldehyde 221099: - dv_tol - Dry deposition velocity of toluene and less reactive aromatics 221100: - dv_xyl - Dry deposition velocity of xylene and more reactive aromatics 221101: - dv_glyald - Dry deposition velocity of glycolaldehyde 221102: - dv_cresol - Dry deposition velocity of cresol 221103: - dv_ald - Dry deposition velocity of acetaldehyde and higher 221104: - dv_ch3coooh - Dry deposition velocity of peracetic acid 221105: - dv_ket - Dry deposition velocity of ketones 221106: - dv_eo2 - Dry deposition velocity of hoch2ch2o2 221107: - dv_glyoxal - Dry deposition velocity of glyoxal 221108: - dv_eo - Dry deposition velocity of hoch2ch2o 221109: - dv_dcb - Dry deposition velocity of unsaturated dicarbonyls 221110: - dv_macr - Dry deposition velocity of methacrolein 221111: - dv_udd - Dry deposition velocity of unsaturated hydroxy dicarbonyl 221112: - dv_c3h7o2 - Dry deposition velocity of isopropyldioxidanyl 221113: - dv_hket - Dry deposition velocity of hydroxy ketone 221114: - dv_c3h7ooh - Dry deposition velocity of isopropyl hydroperoxide 221115: - dv_po2 - Dry deposition velocity of c3h6oho2 221116: - dv_pooh - Dry deposition velocity of c3h6ohooh 221117: - dv_op2 - Dry deposition velocity of higher organic peroxides 221118: - dv_hyac - Dry deposition velocity of hydroxyacetone 221119: - dv_paa - Dry deposition velocity of peroxyacetic acid 221120: - dv_ro2 - Dry deposition velocity of ch3coch2o2 221121: - dv_ethp - Dry deposition velocity of peroxy radical from c2h6 221122: - dv_hc3p - Dry deposition velocity of peroxy radical from hc3 221123: - dv_hc5p - Dry deposition velocity of peroxy radical from hc5 221124: - dv_bigene - Dry deposition velocity of lumped alkenes 221125: - dv_hc8p - Dry deposition velocity of peroxy radical from hc8 221126: - dv_bigalk - Dry deposition velocity of lumped alkanes 221127: - dv_etep - Dry deposition velocity of peroxy radical from c2h4 221128: - dv_mek - Dry deposition velocity of c4h8o 221129: - dv_oltp - Dry deposition velocity of peroxy radical from terminal alkenes 221130: - dv_eneo2 - Dry deposition velocity of c4h9o3 221131: - dv_olip - Dry deposition velocity of peroxy radical from internal alkenes 221132: - dv_meko2 - Dry deposition velocity of ch3coch(oo)ch3 221133: - dv_isopo2 - Dry deposition velocity of peroxy radical from c5h8 221134: - dv_mekooh - Dry deposition velocity of ch3coch(ooh)ch3 221135: - dv_apip - Dry deposition velocity of peroxy radical from a-pinene cyclic terpenes 221136: - dv_mco3 - Dry deposition velocity of ch2=c(ch3)co3 221137: - dv_limp - Dry deposition velocity of peroxy radical from d-limonene cyclic diene 221138: - dv_mvk - Dry deposition velocity of methylvinylketone 221139: - dv_pho - Dry deposition velocity of phenoxy radical 221140: - dv_tolp - Dry deposition velocity of peroxy radical from toluene and less reactive aromatics 221141: - dv_macro2 - Dry deposition velocity of ch3c(o)ch(oo)ch2oh 221142: - dv_xylp - Dry deposition velocity of peroxy radical from xylene and more reactive aromatics 221143: - dv_macrooh - Dry deposition velocity of h3c(o)ch(ooh)ch2oh 221144: - dv_cslp - Dry deposition velocity of peroxy radical from cresol 221145: - dv_mpan - Dry deposition velocity of unsaturated pans 221146: - dv_tco3_c - Dry deposition velocity of unsaturated acyl peroxy radical 221147: - dv_ketp - Dry deposition velocity of peroxy radical from ketones 221148: - dv_alko2 - Dry deposition velocity of c5h11o2 221149: - dv_olnn - Dry deposition velocity of no3-alkenes adduct reacting to form carbonitrates 221150: - dv_alkooh - Dry deposition velocity of c5h11ooh 221151: - dv_olnd - Dry deposition velocity of no3-alkenes adduct reacting via decomposition 221152: - dv_bigald - Dry deposition velocity of hoch2c(ch3)=chcho 221153: - dv_hydrald - Dry deposition velocity of c5h6o2 221154: - dv_sulf - Dry deposition velocity of trop sulfuric acid 221155: - dv_ox - Dry deposition velocity of oxides 221156: - dv_isopno3 - Dry deposition velocity of ch2chc(ch3)(oo)ch2ono2 221157: - dv_onitr - Dry deposition velocity of c3 organic nitrate 221158: - dv_clox - Dry deposition velocity of chlorine oxides 221159: - dv_brox - Dry deposition velocity of bromine oxides 221160: - dv_xooh - Dry deposition velocity of hoch2c(ooh)(ch3)chchoh 221161: - dv_isopooh - Dry deposition velocity of hoch2c(ooh)(ch3)ch=ch2 221162: - dv_toluene - Dry deposition velocity of lumped aromatics 221163: - dv_dmso - Dry deposition velocity of dimethyl sulfoxyde 221164: - dv_tolo2 - Dry deposition velocity of c7h9o5 221165: - dv_tolooh - Dry deposition velocity of c7h10o5 221166: - dv_h2s - Dry deposition velocity of hydrogensulfide 221167: - dv_xoh - Dry deposition velocity of c7h10o6 221168: - dv_noy - Dry deposition velocity of all nitrogen oxides 221169: - dv_cly - Dry deposition velocity of chlorine family 221170: - dv_terpo2 - Dry deposition velocity of c10h16(oh)(oo) 221171: - dv_bry - Dry deposition velocity of bromine family 221172: - dv_terpooh - Dry deposition velocity of c10h18o3 221173: - dv_n - Dry deposition velocity of nitrogen atom 221174: - dv_clo - Dry deposition velocity of chlorine monoxide 221175: - dv_cl_c - Dry deposition velocity of chlorine atom 221176: - dv_bro - Dry deposition velocity of bromine monoxide 221177: - dv_h_c - Dry deposition velocity of hydrogen atom 221178: - dv_ch3 - Dry deposition velocity of methyl group 221179: - dv_addt - Dry deposition velocity of aromatic-ho from toluene and less reactive aromatics 221180: - dv_addx - Dry deposition velocity of aromatic-ho from xylene and more reactive aromatics 221181: - dv_nh4no3 - Dry deposition velocity of ammonium nitrate 221182: - dv_addc - Dry deposition velocity of aromatic-ho from csl 221183: - dv_soa1 - Dry deposition velocity of secondary organic aerosol type 1 221184: - dv_soa2a - Dry deposition velocity of secondary organic aerosol type 2a 221185: - dv_soa2b - Dry deposition velocity of secondary organic aerosol type 2b 221186: - dv_sog1 - Dry deposition velocity of condensable gas type 1 221187: - dv_sog2a - Dry deposition velocity of condensable gas type 2a 221188: - dv_sog2b - Dry deposition velocity of condensable gas type 2b 221189: - dv_so3 - Dry deposition velocity of sulfur trioxide 221190: - dv_ocs_c - Dry deposition velocity of carbonyl sulfide 221191: - dv_br - Dry deposition velocity of bromine atom 221192: - dv_br2 - Dry deposition velocity of bromine 221193: - dv_brcl - Dry deposition velocity of bromine monochloride 221194: - dv_brono2 - Dry deposition velocity of bromine nitrate 221195: - dv_ch2br2 - Dry deposition velocity of dibromomethane 221196: - dv_ch3o - Dry deposition velocity of methoxy radical 221197: - dv_chbr3 - Dry deposition velocity of tribromomethane 221198: - dv_cloo - Dry deposition velocity of asymmetric chlorine dioxide radical 221199: - dv_h2 - Dry deposition velocity of hydrogen 221200: - dv_hcl - Dry deposition velocity of hydrogen chloride 221201: - dv_hco - Dry deposition velocity of formyl radical 221202: - dv_hf - Dry deposition velocity of hydrogen fluoride 221203: - dv_o - Dry deposition velocity of oxygen atom 221204: - dv_o1d - Dry deposition velocity of excited oxygen atom 221205: - dv_o3p - Dry deposition velocity of ground state oxygen atom 221206: - dv_strataer - Dry deposition velocity of stratospheric aerosol 221221: - dv_vso2 - Dry deposition velocity of Volcanic sulfur dioxide 221222: - dv_aroo2 - Dry deposition velocity of Aromatic peroxy radical 221223: - dv_c2h2 - Dry deposition velocity of Ethyne 221224: - dv_ch3cn - Dry deposition velocity of Acetonitrile 221225: - dv_ch3o2no2 - Dry deposition velocity of Methyl peroxy nitrate 221226: - dv_hcn - Dry deposition velocity of Hydrogen cyanide 221227: - dv_hpald1 - Dry deposition velocity of Hydroperoxy aldehydes type 1 221228: - dv_hpald2 - Dry deposition velocity of Hydroperoxy aldehydes type 2 221229: - dv_isopbo2 - Dry deposition velocity of Isoprene peroxy type B 221230: - dv_isopdo2 - Dry deposition velocity of Isoprene peroxy type D 221231: - dv_voca - Dry deposition velocity of Anthropogenic volatile organic compounds 221232: - dv_vocbb - Dry deposition velocity of Biomass burning volatile organic compounds 222001: - acc_dry_depm_o3 - Time-integrated dry deposition mass flux of Ozone 222003: - acc_dry_depm_h2o2 - Time-integrated dry deposition mass flux of Hydrogen peroxide 222005: - acc_dry_depm_co - Time-integrated dry deposition mass flux of Carbon monoxide 222006: - acc_dry_depm_hno3 - Time-integrated dry deposition mass flux of Nitric acid 222007: - acc_dry_depm_ch3ooh - Time-integrated dry deposition mass flux of Methyl peroxide 222008: - acc_dry_depm_hcho - Time-integrated dry deposition mass flux of Formaldehyde 222012: - acc_dry_depm_ald2 - Time-integrated dry deposition mass flux of Aldehydes 222013: - acc_dry_depm_pan - Time-integrated dry deposition mass flux of Peroxyacetyl nitrate 222014: - acc_dry_depm_rooh - Time-integrated dry deposition mass flux of Peroxides 222015: - acc_dry_depm_onit - Time-integrated dry deposition mass flux of Organic nitrates 222016: - acc_dry_depm_c5h8 - Time-integrated dry deposition mass flux of Isoprene 222017: - acc_dry_depm_so2 - Time-integrated dry deposition mass flux of Sulphur dioxide 222019: - acc_dry_depm_nh3 - Time-integrated dry deposition mass flux of Ammonia 222020: - acc_dry_depm_so4 - Time-integrated dry deposition mass flux of Sulfate 222021: - acc_dry_depm_nh4 - Time-integrated dry deposition mass flux of Ammonium 222023: - acc_dry_depm_ch3cocho - Time-integrated dry deposition mass flux of Methyl glyoxal 222024: - acc_dry_depm_o3s - Time-integrated dry deposition mass flux of Ozone (stratospheric) 222027: - acc_dry_depm_no - Time-integrated dry deposition mass flux of Nitrogen monoxide 222028: - acc_dry_depm_ho2 - Time-integrated dry deposition mass flux of Hydroperoxy radical 222029: - acc_dry_depm_ch3o2 - Time-integrated dry deposition mass flux of Methylperoxy radical 222031: - acc_dry_depm_no2 - Time-integrated dry deposition mass flux of Nitrogen dioxide 222032: - acc_dry_depm_no3 - Time-integrated dry deposition mass flux of Nitrate radical 222033: - acc_dry_depm_n2o5 - Time-integrated dry deposition mass flux of Dinitrogen pentoxide 222034: - acc_dry_depm_ho2no2 - Time-integrated dry deposition mass flux of Pernitric acid 222042: - acc_dry_depm_ch3oh - Time-integrated dry deposition mass flux of Methanol 222043: - acc_dry_depm_hcooh - Time-integrated dry deposition mass flux of Formic acid 222044: - acc_dry_depm_mcooh - Time-integrated dry deposition mass flux of Methacrylic acid 222045: - acc_dry_depm_c2h6 - Time-integrated dry deposition mass flux of Ethane 222046: - acc_dry_depm_c2h5oh - Time-integrated dry deposition mass flux of Ethanol 222050: - acc_dry_depm_ispd - Time-integrated dry deposition mass flux of Methacrolein 222051: - acc_dry_depm_no3_a - Time-integrated dry deposition mass flux of Nitrate 222052: - acc_dry_depm_ch3coch3 - Time-integrated dry deposition mass flux of Acetone 222086: - acc_dry_depm_hono - Time-integrated dry deposition mass flux of Nitrous acid 222099: - acc_dry_depm_tol - Time-integrated dry deposition mass flux of Toluene and less reactive aromatics 222100: - acc_dry_depm_xyl - Time-integrated dry deposition mass flux of Xylene and more reactive aromatics 222101: - acc_dry_depm_glyald - Time-integrated dry deposition mass flux of Glycolaldehyde 222107: - acc_dry_depm_gly - Time-integrated dry deposition mass flux of Glyoxal 222118: - acc_dry_depm_hyac - Time-integrated dry deposition mass flux of Hydroxyacetone 222161: - acc_dry_depm_isopooh - Time-integrated dry deposition mass flux of all hydroxy-peroxides products of the reaction of hydroxy-isoprene adducts with O2 222224: - acc_dry_depm_ch3cn - Time-integrated dry deposition mass flux of Acetonitrile 222226: - acc_dry_depm_hcn - Time-integrated dry deposition mass flux of Hydrogen cyanide 223001: - acc_wet_depm_o3 - Time-integrated wet deposition mass flux of Ozone 223003: - acc_wet_depm_h2o2 - Time-integrated wet deposition mass flux of Hydrogen peroxide 223006: - acc_wet_depm_hno3 - Time-integrated wet deposition mass flux of Nitric acid 223007: - acc_wet_depm_ch3ooh - Time-integrated wet deposition mass flux of Methyl peroxide 223008: - acc_wet_depm_hcho - Time-integrated wet deposition mass flux of Formaldehyde 223012: - acc_wet_depm_ald2 - Time-integrated wet deposition mass flux of Aldehydes 223013: - acc_wet_depm_pan - Time-integrated wet deposition mass flux of Peroxyacetyl nitrate 223014: - acc_wet_depm_rooh - Time-integrated wet deposition mass flux of Peroxides 223015: - acc_wet_depm_onit - Time-integrated wet deposition mass flux of Organic nitrates 223016: - acc_wet_depm_c5h8 - Time-integrated wet deposition mass flux of Isoprene 223017: - acc_wet_depm_so2 - Time-integrated wet deposition mass flux of Sulphur dioxide 223019: - acc_wet_depm_nh3 - Time-integrated wet deposition mass flux of Ammonia 223020: - acc_wet_depm_so4 - Time-integrated wet deposition mass flux of Sulfate 223021: - acc_wet_depm_nh4 - Time-integrated wet deposition mass flux of Ammonium 223022: - acc_wet_depm_msa - Time-integrated wet deposition mass flux of Methane sulfonic acid 223023: - acc_wet_depm_ch3cocho - Time-integrated wet deposition mass flux of Methyl glyoxal 223025: - acc_wet_depm_co - Time-integrated wet deposition mass flux of Carbon monoxide 223026: - acc_wet_depm_pb - Time-integrated wet deposition mass flux of Lead 223027: - acc_wet_depm_no - Time-integrated wet deposition mass flux of Nitrogen monoxide 223028: - acc_wet_depm_ho2 - Time-integrated wet deposition mass flux of Hydroperoxy radical 223029: - acc_wet_depm_ch3o2 - Time-integrated wet deposition mass flux of Methylperoxy radical 223031: - acc_wet_depm_no2 - Time-integrated wet deposition mass flux of Nitrogen dioxide 223032: - acc_wet_depm_no3 - Time-integrated wet deposition mass flux of Nitrate radical 223033: - acc_wet_depm_n2o5 - Time-integrated wet deposition mass flux of Dinitrogen pentoxide 223034: - acc_wet_depm_ho2no2 - Time-integrated wet deposition mass flux of Pernitric acid 223042: - acc_wet_depm_ch3oh - Time-integrated wet deposition mass flux of Methanol 223043: - acc_wet_depm_hcooh - Time-integrated wet deposition mass flux of Formic acid 223044: - acc_wet_depm_mcooh - Time-integrated wet deposition mass flux of Methacrylic acid 223045: - acc_wet_depm_c2h6 - Time-integrated wet deposition mass flux of Ethane 223046: - acc_wet_depm_c2h5oh - Time-integrated wet deposition mass flux of Ethanol 223050: - acc_wet_depm_ispd - Time-integrated wet deposition mass flux of Methacrolein 223051: - acc_wet_depm_no3_a - Time-integrated wet deposition mass flux of Nitrate 223052: - acc_wet_depm_ch3coch3 - Time-integrated wet deposition mass flux of Acetone 223064: - acc_wet_depm_clono2 - Time-integrated wet deposition mass flux of Chlorine nitrate 223065: - acc_wet_depm_hocl - Time-integrated wet deposition mass flux of Hypochlorous acid 223068: - acc_wet_depm_hbr - Time-integrated wet deposition mass flux of Hydrogen bromide 223070: - acc_wet_depm_hobr - Time-integrated wet deposition mass flux of Hypobromous acid 223086: - acc_wet_depm_hono - Time-integrated wet deposition mass flux of Nitrous acid 223099: - acc_wet_depm_tol - Time-integrated wet deposition mass flux of Toluene and less reactive aromatics 223100: - acc_wet_depm_xyl - Time-integrated wet deposition mass flux of Xylene and more reactive aromatics 223101: - acc_wet_depm_glyald - Time-integrated wet deposition mass flux of Glycolaldehyde 223107: - acc_wet_depm_gly - Time-integrated wet deposition mass flux of Glyoxal 223118: - acc_wet_depm_hyac - Time-integrated wet deposition mass flux of Hydroxyacetone 223161: - acc_wet_depm_isopooh - Time-integrated wet deposition mass flux of all hydroxy-peroxides products of the reaction of hydroxy-isoprene adducts with O2 223186: - acc_wet_depm_sog1 - Time-integrated wet deposition mass flux of Condensable gas type 1 223187: - acc_wet_depm_sog2a - Time-integrated wet deposition mass flux of Condensable gas type 2a 223188: - acc_wet_depm_sog2b - Time-integrated wet deposition mass flux of Condensable gas type 2b 223194: - acc_wet_depm_brono2 - Time-integrated wet deposition mass flux of Bromine nitrate 223200: - acc_wet_depm_hcl - Time-integrated wet deposition mass flux of Hydrogen chloride 223224: - acc_wet_depm_ch3cn - Time-integrated wet deposition mass flux of Acetonitrile 223226: - acc_wet_depm_hcn - Time-integrated wet deposition mass flux of Hydrogen cyanide 223227: - acc_wet_depm_hpald1 - Time-integrated wet deposition mass flux of Hydroperoxy aldehydes type 1 223228: - acc_wet_depm_hpald2 - Time-integrated wet deposition mass flux of Hydroperoxy aldehydes type 2 228001: - cin - Convective inhibition 228002: - orog - Orography 228003: - zust - Friction velocity 228004: - avg_2t - Time-mean 2 metre temperature 228005: - avg_10ws - Time-mean 10 metre wind speed 228006: - meantcc - Mean total cloud cover 228007: - dl - Lake total depth 228008: - lmlt - Lake mix-layer temperature 228009: - lmld - Lake mix-layer depth 228010: - lblt - Lake bottom temperature 228011: - ltlt - Lake total layer temperature 228012: - lshf - Lake shape factor 228013: - lict - Lake ice surface temperature 228014: - licd - Lake ice total depth 228015: - dndzn - Minimum vertical gradient of refractivity inside trapping layer 228016: - dndza - Mean vertical gradient of refractivity inside trapping layer 228017: - dctb - Duct base height 228018: - tplb - Trapping layer base height 228019: - tplt - Trapping layer top height 228020: - degm10l - Geometric height of -10 degrees C atmospheric isothermal level above ground 228021: - fdir - Surface direct short-wave (solar) radiation 228022: - cdir - Surface direct short-wave radiation, clear sky 228023: - cbh - Cloud base height 228024: - deg0l - Geometric height of 0 degrees C atmospheric isothermal level above ground - deg0 228025: - hvis - Horizontal visibility 228026: - mx2t3 - Maximum temperature at 2 metres in the last 3 hours 228027: - mn2t3 - Minimum temperature at 2 metres in the last 3 hours 228028: - 10fg3 - Maximum 10 metre wind gust in the last 3 hours 228029: - i10fg - Instantaneous 10 metre wind gust 228030: - rhw - Relative humidity with respect to water 228031: - rhi - Relative humidity with respect to ice 228032: - asn - Snow albedo 228034: - fcpc - Fraction of convective precipitation cover 228035: - mxcape6 - Maximum CAPE in the last 6 hours 228036: - mxcapes6 - Maximum CAPES in the last 6 hours 228037: - 2rhw - 2 metre relative humidity with respect to water 228038: - lwcs - Liquid water content in snow pack 228039: - sm - Soil moisture 228040: - swi1 - Soil wetness index in layer 1 228041: - swi2 - Soil wetness index in layer 2 228042: - swi3 - Soil wetness index in layer 3 228043: - swi4 - Soil wetness index in layer 4 228044: - capes - Convective available potential energy shear 228045: - trpp - Tropopause pressure 228046: - hcct - Height of convective cloud top 228047: - hwbt0 - Height of zero-degree wet-bulb temperature 228048: - hwbt1 - Height of one-degree wet-bulb temperature 228050: - litoti - Instantaneous total lightning flash density 228051: - litota1 - Averaged total lightning flash density in the last hour 228052: - licgi - Instantaneous cloud-to-ground lightning flash density 228053: - licga1 - Averaged cloud-to-ground lightning flash density in the last hour 228054: - ucq - Unbalanced component of specific humidity 228055: - ucclwc - Unbalanced component of specific cloud liquid water content 228056: - ucciwc - Unbalanced component of specific cloud ice water content 228057: - litota3 - Averaged total lightning flash density in the last 3 hours 228058: - litota6 - Averaged total lightning flash density in the last 6 hours 228059: - licga3 - Averaged cloud-to-ground lightning flash density in the last 3 hours 228060: - licga6 - Averaged cloud-to-ground lightning flash density in the last 6 hours 228070: - smnnob - SMOS observed soil moisture retrieved using neural network 228071: - smnner - SMOS observed soil moisture uncertainty retrieved using neural network 228072: - smnnrfi - SMOS radio frequency interference probability 228073: - smnnnb - SMOS number of observations per grid point 228074: - smnntim - SMOS observation time for the satellite soil moisture data 228078: - gppbfas - GPP coefficient from Biogenic Flux Adjustment System 228079: - recbfas - Rec coefficient from Biogenic Flux Adjustment System 228080: - aco2nee - Accumulated Carbon Dioxide Net Ecosystem Exchange 228081: - aco2gpp - Accumulated Carbon Dioxide Gross Primary Production 228082: - aco2rec - Accumulated Carbon Dioxide Ecosystem Respiration 228083: - fco2nee - Carbon dioxide net ecosystem exchange flux 228084: - fco2gpp - Carbon dioxide gross primary production flux 228085: - fco2rec - Carbon dioxide ecosystem respiration flux 228086: - sm20 - Soil moisture top 20 cm 228087: - sm100 - Soil moisture top 100 cm 228088: - tcslw - Total column supercooled liquid water 228089: - tcrw - Total column rain water 228090: - tcsw - Total column snow water 228091: - ccf - Canopy cover fraction 228092: - stf - Soil texture fraction 228093: - swv - Volumetric soil moisture 228094: - ist - Ice temperature 228095: - st20 - Soil temperature top 20 cm 228096: - st100 - Soil temperature top 100 cm 228100: - evatc - Evaporation from the top of canopy 228101: - evabs - Evaporation from bare soil 228102: - evaow - Evaporation from open water surfaces excluding oceans 228103: - evavt - Evaporation from vegetation transpiration 228104: - e_wlch4 - Atmosphere emission mass flux of Methane from Wetlands 228105: - sif740 - Solar induced Chlorophyll fluorescence at 740nm 228106: - sif755 - Solar induced Chlorophyll fluorescence at 755nm 228107: - sif771 - Solar induced Chlorophyll fluorescence at 771nm 228108: - sif757 - Solar induced Chlorophyll fluorescence at 757nm 228109: - acc_e_wlch4 - Accumulated mass emission of methane from Wetlands 228129: - ssrdc - Surface short-wave (solar) radiation downward clear-sky 228130: - strdc - Surface long-wave (thermal) radiation downward clear-sky 228131: - u10n - 10 metre u-component of neutral wind 228132: - v10n - 10 metre v-component of neutral wind 228134: - vtnowd - V-tendency from non-orographic wave drag 228136: - utnowd - U-tendency from non-orographic wave drag 228139: - st - Soil temperature 228141: - sd - Snow depth water equivalent 228143: - cp - Convective precipitation 228144: - sf - Snowfall water equivalent 228164: - tcc - Total Cloud Cover 228170: - cap - Field capacity 228171: - wilt - Wilting point 228205: - ro - Water runoff and drainage 228216: - fzra - Accumulated freezing rain 228217: - ilspf - Instantaneous large-scale precipitation fraction 228218: - crr - Convective rain rate 228219: - lsrr - Large scale rain rate 228220: - csfr - Convective snowfall rate water equivalent 228221: - lssfr - Large scale snowfall rate water equivalent 228222: - mxtpr3 - Maximum total precipitation rate in the last 3 hours 228223: - mntpr3 - Minimum total precipitation rate in the last 3 hours 228224: - mxtpr6 - Maximum total precipitation rate in the last 6 hours 228225: - mntpr6 - Minimum total precipitation rate in the last 6 hours 228226: - mxtpr - Maximum total precipitation rate since previous post-processing 228227: - mntpr - Minimum total precipitation rate since previous post-processing 228228: - tp - Total Precipitation 228229: - smos_tb_cdfa - SMOS first Brightness Temperature Bias Correction parameter 228230: - smos_tb_cdfb - SMOS second Brightness Temperature Bias Correction parameter 228231: - mlcape50 - Mixed-layer CAPE in the lowest 50 hPa 228232: - mlcin50 - Mixed-layer CIN in the lowest 50 hPa 228233: - mlcape100 - Mixed-layer CAPE in the lowest 100 hPa 228234: - mlcin100 - Mixed-layer CIN in the lowest 100 hPa 228235: - mucape - Most-unstable CAPE 228236: - mucin - Most-unstable CIN 228237: - mudlp - Departure level of the most unstable parcel expressed as Pressure 228239: - 200u - 200 metre U wind component 228240: - 200v - 200 metre V wind component 228241: - 200si - 200 metre wind speed 228242: - fdif - Surface solar radiation diffuse total sky 228243: - cdif - Surface solar radiation diffuse clear-sky 228244: - aldr - Surface albedo of direct radiation 228245: - aldf - Surface albedo of diffuse radiation 228246: - 100u - 100 metre U wind component 228247: - 100v - 100 metre V wind component 228248: - tccsw - Surface short wave-effective total cloudiness 228249: - 100si - 100 metre wind speed 228250: - irrfr - Irrigation fraction 228251: - pev - Potential evaporation 228252: - irr - Irrigation 228253: - ascat_sm_cdfa - ASCAT first soil moisture CDF matching parameter 228254: - ascat_sm_cdfb - ASCAT second soil moisture CDF matching parameter 228255: - tcclw - Surface long wave-effective total cloudiness 229001: - cur - Urban cover 229002: - cro - Road Cover 229003: - cbu - Building cover 229004: - bldh - Building height 229005: - hwr - Vertical-to-horizontal area ratio 229006: - bhstd - Standard deviation of building height 229007: - cwe - Wetland cover 229008: - twe - Wetland type 229009: - cirr - Irrigation cover 229010: - c4cr - C4 crop cover 229011: - c4gr - C4 grass cover 230008: - srovar - Surface runoff (variable resolution) 230009: - ssrovar - Sub-surface runoff (variable resolution) 230020: - parcsvar - Clear sky surface photosynthetically active radiation (variable resolution) 230021: - fdirvar - Total sky direct solar radiation at surface (variable resolution) 230022: - cdirvar - Clear-sky direct solar radiation at surface (variable resolution) 230044: - esvar - Snow evaporation (variable resolution) 230045: - smltvar - Snowmelt (variable resolution) 230046: - sdurvar - Solar duration (variable resolution) 230047: - dsrpvar - Direct solar radiation (variable resolution) 230050: - lspfvar - Large-scale precipitation fraction (variable resolution) 230057: - uvbvar - Downward UV radiation at the surface (variable resolution) 230058: - parvar - Photosynthetically active radiation at the surface (variable resolution) 230080: - aco2neevar - Accumulated Carbon Dioxide Net Ecosystem Exchange (variable resolution) 230081: - aco2gppvar - Accumulated Carbon Dioxide Gross Primary Production (variable resolution) 230082: - aco2recvar - Accumulated Carbon Dioxide Ecosystem Respiration (variable resolution) 230129: - ssrdcvar - Surface solar radiation downward clear-sky (variable resolution) 230130: - strdcvar - Surface thermal radiation downward clear-sky (variable resolution) 230142: - lspvar - Stratiform precipitation (Large-scale precipitation) (variable resolution) 230143: - cpvar - Convective precipitation (variable resolution) 230144: - sfvar - Snowfall (convective + stratiform) (variable resolution) 230145: - bldvar - Boundary layer dissipation (variable resolution) 230146: - sshfvar - Surface sensible heat flux (variable resolution) 230147: - slhfvar - Surface latent heat flux (variable resolution) 230169: - ssrdvar - Surface solar radiation downwards (variable resolution) 230174: - alvar - Albedo (variable resolution) 230175: - strdvar - Surface thermal radiation downwards (variable resolution) 230176: - ssrvar - Surface net solar radiation (variable resolution) 230177: - strvar - Surface net thermal radiation (variable resolution) 230178: - tsrvar - Top net solar radiation (variable resolution) 230179: - ttrvar - Top net thermal radiation (variable resolution) 230180: - ewssvar - East-West surface stress (variable resolution) 230181: - nsssvar - North-South surface stress (variable resolution) 230182: - evar - Evaporation (variable resolution) 230189: - sundvar - Sunshine duration (variable resolution) 230195: - lgwsvar - Longitudinal component of gravity wave stress (variable resolution) 230196: - mgwsvar - Meridional component of gravity wave stress (variable resolution) 230197: - gwdvar - Gravity wave dissipation (variable resolution) 230198: - srcvar - Skin reservoir content (variable resolution) 230205: - rovar - Runoff (variable resolution) 230208: - tsrcvar - Top net solar radiation, clear sky (variable resolution) 230209: - ttrcvar - Top net thermal radiation, clear sky (variable resolution) 230210: - ssrcvar - Surface net solar radiation, clear sky (variable resolution) 230211: - strcvar - Surface net thermal radiation, clear sky (variable resolution) 230212: - tisrvar - TOA incident solar radiation (variable resolution) 230213: - vimdvar - Vertically integrated moisture divergence (variable resolution) 230216: - fzravar - Accumulated freezing rain (variable resolution) 230228: - tpvar - Total precipitation (variable resolution) 230239: - csfvar - Convective snowfall (variable resolution) 230240: - lsfvar - Large-scale snowfall (variable resolution) 230251: - pevvar - Potential evaporation (variable resolution) 231001: - fzrawe - Accumulated freezing rain water equivalent 231002: - rowe - Runoff water equivalent (surface plus subsurface) 231003: - eswe - Snow evaporation water equivalent 231004: - pevr - Potential evaporation rate 231005: - peva - Potential evaporation 231006: - tifr - Tile fraction 231007: - tipe - Tile percentage 231008: - flsrm - Forecast logarithm of surface roughness length for moisture 231009: - surfror - Surface runoff rate 231010: - surfro - Surface runoff 231011: - ssurfror - Sub-surface runoff rate 231012: - ssurfro - Sub-surface runoff 231013: - rfl04 - Reflectance in 0.4 micron channel 231014: - vdiv - Vertical divergence 231015: - dtc - Drag thermal coefficient 231016: - dec - Drag evaporation coefficient 231017: - pdhs - Pressure departure from hydrostatic state 231018: - snrf - Surface net radiation flux (SW and LW) 231019: - tnrf - Top net radiation flux (SW and LW) 231020: - mtnrf - Time-mean top net radiation flux (SW and LW) 231021: - gits - Global irradiance on tilted surfaces 231022: - eagr - Eady growth rate 231023: - tdtc - Tropical cyclones track density 231024: - cant - Canopy air temperature 231025: - swit - Soil wetness index (total layer) 231026: - swir - Soil wetness index (root zone) 231027: - swil - Soil wetness index (layer) 231028: - ddrf - Distance downward from roof surface 231029: - diws - Distance inward from outer wall surface 231030: - ddrd - Distance downward from road surface 231031: - rpc - Renewable power capacity 231032: - rppr - Renewable power production rate 231033: - rpp - Renewable power production 231034: - wpc - Wind power capacity 231035: - wppr - Wind power production rate 231036: - wpp - Wind power production 231037: - pvpc - Solar photovoltaic (PV) power capacity 231038: - pvppr - Solar photovoltaic (PV) power production rate 231039: - pvpp - Solar photovoltaic (PV) power production 231040: - tgrp - Graupel (snow pellets) precipitation 231041: - litotint - Time-integrated total lightning flash density 231042: - maxtcg - Maximum total column integrated graupel (snow pellets) 231043: - minvis - Minimum visibility 231044: - hthg - Geometric height of theta level above ground 231045: - pcdb - Pressure at cloud base 231046: - hacg - Geometric height of adiabatic condensation level above ground 231047: - hfcg - Geometric height of free convection level above ground 231048: - hnbg - Geometric height of neutral buoyancy level above ground 231049: - deg3l - Geometric height of 3 degrees C atmospheric isothermal level above ground 231050: - rft - Roof temperature 231051: - wlt - Wall temperature 231052: - rdt - Road temperature 231053: - sdrf - Snow depth water equivalent on roof 231054: - sdrd - Snow depth water equivalent on road 231055: - urct - Urban canyon temperature 231056: - urcq - Urban canyon specific humidity 231057: - csfwe - Convective snowfall water equivalent 231058: - lsfwe - Large-scale snowfall water equivalent 231059: - lslt - Lake surface temperature 231060: - sbrn - Surface bulk Richardson number 231061: - mx2r - Time-maximum 2 metre relative humidity 231062: - mn2r - Time-minimum 2 metre relative humidity 231063: - srhe - Surface roughness for heat 231064: - srmo - Surface roughness for moisture 231065: - esrwe - Snow evaporation rate water equivalent 231066: - rare - Radar reflectivity 231067: - pcdc - Pressure at cloud ceiling 231068: - visp - Visibility through precipitation 231069: - h0thg - Geometric height of 0 degrees C theta level above ground 231070: - h1thg - Geometric height of 1 degree C theta level above ground 231071: - h1p5thg - Geometric height of 1.5 degrees C theta level above ground 231072: - vswrz - Volumetric soil moisture (root zone) 231500: - hits - Thunderstorm hazard index 231501: - hiswf - Surface water flooding hazard index 231502: - hipa - Polluted air hazard index 231503: - hiss - Storm surge hazard index 231504: - hicw - Cold wave hazard index 231505: - hihf - Frost (hoar frost) hazard index 231506: - hihw - Heatwave hazard index 231507: - hiw - Wind hazard index 231508: - hiwf - Wildfires hazard index 232000: - fba - Burned area 232001: - bia - Burning area 232002: - baa - Burnable area 232003: - ubaa - Un-burnable area 232004: - fuell - Fuel load 232005: - combc - Combustion completeness 232006: - fuelmc - Fuel moisture content 232007: - llfl - Live leaf fuel load 232008: - lwfl - Live wood fuel load 232009: - dlfl - Dead leaf fuel load 232010: - dwfl - Dead wood fuel load 232011: - lfmc - Live fuel moisture content 232012: - fdlmc - Fine dead leaf moisture content 232013: - ddlmc - Dense dead leaf moisture content 232014: - fdwmc - Fine dead wood moisture content 232015: - ddwmc - Dense dead wood moisture content 232016: - lfmclv - Live fuel moisture content in low vegetation 232017: - lfmchv - Live fuel moisture content in high vegetation 233000: - tvige - Time-integrated total column vertically-integrated eastward geopotential flux 233001: - tvign - Time-integrated total column vertically-integrated northward geopotential flux 233002: - tviwgd - Time-integrated total column vertically-integrated divergence of water geopotential flux 233003: - tvigd - Time-integrated total column vertically-integrated divergence of geopotential flux 233004: - tviee - Time-integrated total column vertically-integrated eastward enthalpy flux 233005: - tvien - Time-integrated total column vertically-integrated northward enthalpy flux 233006: - tvikee - Time-integrated total column vertically-integrated eastward kinetic energy flux 233007: - tviken - Time-integrated total column vertically-integrated northward kinetic energy flux 233008: - tvitee - Time-integrated total column vertically-integrated eastward total energy flux 233009: - tviten - Time-integrated total column vertically-integrated northward total energy flux 233010: - tvied - Time-integrated total column vertically-integrated divergence of enthalpy flux 233011: - tviked - Time-integrated total column vertically-integrated divergence of kinetic energy flux 233012: - tvited - Time-integrated total column vertically-integrated divergence of total energy flux 233013: - tviwed - Time-integrated total column vertically-integrated divergence of water enthalpy flux 233014: - tvimad - Time-integrated total column vertically-integrated divergence of mass flux 233015: - tvimae - Time-integrated total column vertically-integrated eastward mass flux 233016: - tviman - Time-integrated total column vertically-integrated northward mass flux 233017: - tviwvd - Time-integrated total column vertically-integrated divergence of water vapour flux 233018: - tviclwd - Time-integrated total column vertically-integrated divergence of cloud liquid water flux 233019: - tviciwd - Time-integrated total column vertically-integrated divergence of cloud ice water flux 233020: - tvird - Time-integrated total column vertically-integrated divergence of rain flux 233021: - tvisd - Time-integrated total column vertically-integrated divergence of snow flux 233022: - tviwve - Time-integrated total column vertically-integrated eastward water vapour flux 233023: - tviwvn - Time-integrated total column vertically-integrated northward water vapour flux 233024: - tviclwe - Time-integrated total column vertically-integrated eastward cloud liquid water flux 233025: - tviclwn - Time-integrated total column vertically-integrated northward cloud liquid water flux 233026: - tviciwe - Time-integrated total column vertically-integrated eastward cloud ice water flux 233027: - tviciwn - Time-integrated total column vertically-integrated northward cloud ice water flux 233028: - tvire - Time-integrated total column vertically-integrated eastward rain flux 233029: - tvirn - Time-integrated total column vertically-integrated northward rain flux 233030: - tvise - Time-integrated total column vertically-integrated eastward snow flux 233031: - tvisn - Time-integrated total column vertically-integrated northward snow flux 233032: - tvioze - Time-integrated total column vertically-integrated eastward ozone flux 233033: - tviozn - Time-integrated total column vertically-integrated northward ozone flux 233034: - tviozd - Time-integrated total column vertically-integrated divergence of ozone flux 233035: - tvions - Time-integrated total column vertically-integrated net source of ozone 234139: - sts - Surface temperature significance 234151: - msls - Mean sea level pressure significance 234167: - 2ts - 2 metre temperature significance 234228: - tps - Total precipitation significance 235001: - avg_ttswr - Time-mean temperature tendency due to short-wave radiation 235002: - avg_ttlwr - Time-mean temperature tendency due to long-wave radiation 235003: - avg_ttswrcs - Time-mean temperature tendency due to short wave radiation, clear sky 235004: - avg_ttlwrcs - Time-mean temperature tendency due to long-wave radiation, clear sky 235005: - avg_ttpm - Time-mean temperature tendency due to parametrisations 235006: - avg_qtpm - Time-mean specific humidity tendency due to parametrisations 235007: - avg_utpm - Time-mean eastward wind tendency due to parametrisations 235008: - avg_vtpm - Time-mean northward wind tendency due to parametrisations 235009: - avg_umf - Time-mean updraught mass flux 235010: - avg_dmf - Time-mean downdraught mass flux 235011: - avg_udr - Time-mean updraught detrainment rate 235012: - avg_ddr - Time-mean downdraught detrainment rate 235013: - avg_tpf - Time-mean total precipitation flux 235014: - avg_tdch - Time-mean turbulent diffusion coefficient for heat 235015: - tirf - Time integral of rain flux 235017: - tisemf - Time integral of surface eastward momentum flux 235018: - tisnmf - Time integral of surface northward momentum flux 235019: - tislhef - Time integral of surface latent heat evaporation flux 235020: - avg_surfror - Time-mean surface runoff rate 235021: - avg_ssurfror - Time-mean sub-surface runoff rate 235022: - avg_parcsf - Time-mean surface photosynthetically active radiation flux, clear sky 235023: - avg_esrwe - Time-mean snow evaporation rate water equivalent 235024: - avg_smr - Time-mean snow melt rate 235025: - avg_imagss - Time-mean magnitude of turbulent surface stress 235026: - avg_ilspf - Time-mean large-scale precipitation fraction 235027: - avg_sduvrf - Time-mean surface downward UV radiation flux 235028: - avg_sparf - Time-mean surface photosynthetically active radiation flux 235029: - avg_lsprate - Time-mean large-scale precipitation rate 235030: - avg_cpr - Time-mean convective precipitation rate 235031: - avg_tsrwe - Time-mean total snowfall rate water equivalent 235032: - avg_ibld - Time-mean boundary layer dissipation 235033: - avg_ishf - Time-mean surface sensible heat flux 235034: - avg_slhtf - Time-mean surface latent heat flux 235035: - avg_sdswrf - Time-mean surface downward short-wave radiation flux 235036: - avg_sdlwrf - Time-mean surface downward long-wave radiation flux 235037: - avg_snswrf - Time-mean surface net short-wave radiation flux 235038: - avg_snlwrf - Time-mean surface net long-wave radiation flux 235039: - avg_tnswrf - Time-mean top net short-wave radiation flux 235040: - avg_tnlwrf - Time-mean top net long-wave radiation flux 235041: - avg_iews - Time-mean eastward turbulent surface stress 235042: - avg_inss - Time-mean northward turbulent surface stress 235043: - avg_ie - Time-mean moisture flux 235044: - avg_sdf - Time-mean sunshine duration fraction 235045: - avg_iegwss - Time-mean eastward gravity wave surface stress 235046: - avg_ingwss - Time-mean northward gravity wave surface stress 235047: - avg_igwd - Time-mean gravity wave dissipation 235048: - avg_rorwe - Time-mean runoff rate water equivalent (surface plus subsurface) 235049: - avg_tnswrfcs - Time-mean top net short-wave radiation flux, clear sky 235050: - avg_tnlwrfcs - Time-mean top net long-wave radiation flux, clear sky 235051: - avg_snswrfcs - Time-mean surface net short-wave radiation flux, clear sky 235052: - avg_snlwrfcs - Time-mean surface net long-wave radiation flux, clear sky 235053: - avg_tdswrf - Time mean top downward short-wave radiation flux 235054: - avg_vimdf - Time-mean total column vertically-integrated moisture divergence flux 235055: - avg_tprate - Time-mean total precipitation rate 235056: - avg_csfr - Time-mean convective snowfall rate water equivalent 235057: - avg_lssfr - Time-mean large scale snowfall rate water equivalent 235058: - avg_sdirswrf - Time-mean surface direct short-wave radiation flux 235059: - avg_sdirswrfcs - Time-mean surface direct short-wave radiation flux, clear sky 235060: - msdfswrf - Mean surface diffuse short-wave radiation flux 235061: - avg_sdifswrfcs - Time-mean surface diffuse short-wave radiation flux, clear sky 235062: - avg_fco2nee - Time-mean carbon dioxide net ecosystem exchange flux 235063: - avg_fco2gpp - Time-mean carbon dioxide gross primary production flux 235064: - avg_fco2rec - Time-mean carbon dioxide ecosystem respiration flux 235065: - mrr - Mean rain rate 235066: - mcrr - Mean convective rain rate 235067: - mlsrr - Mean large-scale rain rate 235068: - avg_sdswrfcs - Time-mean surface downward short-wave radiation flux, clear sky 235069: - avg_sdlwrfcs - Time-mean surface downward long-wave radiation flux, clear sky 235070: - avg_pevr - Time-mean potential evaporation rate 235071: - tislhsf - Time integral of surface latent heat sublimation flux 235072: - tisef - Time integral of snow evaporation flux 235073: - tietrf - Time integral of evapotranspiration flux 235074: - avg_etr - Time-mean evapotranspiration rate 235075: - tipet - Time integral of potential evapotranspiration rate 235076: - avg_petr - Time-mean potential evapotranspiration rate 235077: - avg_vsw - Time-mean volumetric soil moisture 235078: - avg_sd - Time-mean snow depth water equivalent 235079: - avg_skt - Time-mean skin temperature 235080: - avg_rsn - Time-mean snow density 235081: - avg_cvl - Time-mean low vegetation cover 235082: - avg_cvh - Time-mean high vegetation cover 235083: - avg_ci - Time-mean sea ice area fraction 235084: - avg_sst - Time-mean sea surface temperature 235085: - avg_lai_lv - Time-mean leaf area index, low vegetation 235086: - avg_lai_hv - Time-mean leaf area index, high vegetation 235087: - avg_tclw - Time-mean total column liquid water 235088: - avg_tciw - Time-mean total column cloud ice water 235089: - avg_2sh - Time-mean 2 metre specific humidity 235090: - avg_lmlt - Time-mean lake mix-layer temperature 235091: - avg_lmld - Time-mean lake mix-layer depth 235092: - avg_2r - Time-mean 2 metre relative humidity 235093: - avg_fscov - Time-mean fraction of snow cover 235094: - avg_sot - Time-mean soil temperature 235095: - avg_sde - Time-mean snow depth 235096: - avg_snowc - Time-mean snow cover 235097: - avg_ws - Time-mean wind speed 235098: - avg_pres - Time-mean pressure 235099: - avg_chnk - Time-mean charnock 235100: - avg_pv - Time-mean potential vorticity 235101: - avg_crwc - Time-mean specific rain water content 235102: - avg_cswc - Time-mean specific snow water content 235103: - avg_etadot - Time-mean eta-coordinate vertical velocity 235105: - avg_vis - Time-mean visibility 235106: - avg_wdir - Time-mean wind direction 235107: - avg_tcsw - Time-mean total column snow water 235108: - avg_lcc - Time-mean low cloud cover 235109: - avg_mcc - Time-mean medium cloud cover 235110: - avg_hcc - Time-mean high cloud cover 235111: - avg_tcrw - Time-mean total column rain water 235113: - avg_sm20 - Time-mean soil moisture top 20 cm 235114: - avg_sm100 - Time-mean soil moisture top 100 cm 235115: - avg_st20 - Time-mean soil temperature top 20 cm 235116: - avg_st100 - Time-mean soil temperature top 100 cm 235117: - avg_mucape - Time-mean most-unstable CAPE 235118: - avg_vsw20 - Time-mean volumetric soil moisture top 20 cm 235119: - avg_vsw100 - Time-mean volumetric soil moisture top 100 cm 235120: - avg_tcolg - Time-mean total column vertically-integrated graupel (snow pellets) 235129: - avg_z - Time-mean geopotential 235130: - avg_t - Time-mean temperature 235131: - avg_u - Time-mean U component of wind 235132: - avg_v - Time-mean V component of wind 235133: - avg_q - Time-mean specific humidity 235134: - avg_sp - Time-mean surface pressure 235135: - avg_w - Time-mean vertical velocity 235136: - avg_tcw - Time-mean total column water 235137: - avg_tcwv - Time-mean total column vertically-integrated water vapour 235138: - avg_vo - Time-mean vorticity (relative) 235141: - avg_sd_m - Time-mean snow depth 235149: - avg_snrf - Time-mean surface net radiation flux (SW and LW) 235150: - avg_tnrf - Time-mean top net radiation flux (SW and LW) 235151: - avg_msl - Time-mean mean sea level pressure 235152: - avg_lnsp - Time-mean logarithm of surface pressure 235155: - avg_d - Time-mean divergence 235157: - avg_r - Time-mean relative humidity 235159: - avg_blh - Time-mean boundary layer height 235165: - avg_10u - Time-mean 10 metre U wind component 235166: - avg_10v - Time-mean 10 metre V wind component 235168: - avg_2d - Time-mean 2 metre dewpoint temperature 235186: - avg_lcc_frac - Time-mean low cloud cover 235187: - avg_mcc_frac - Time-mean medium cloud cover 235188: - avg_hcc_frac - Time-mean high cloud cover 235189: - avg_suns - Time-mean sunshine 235203: - avg_o3 - Time-mean ozone mass mixing ratio 235238: - avg_tsn - Time-mean temperature of snow layer 235243: - avg_fal_frac - Time-mean forecast albedo 235244: - avg_fsr - Time-mean forecast surface roughness 235245: - avg_flsr - Time-mean forecast logarithm of surface roughness for heat 235246: - avg_clwc - Time-mean specific cloud liquid water content 235247: - avg_ciwc - Time-mean specific cloud ice water content 235248: - avg_cc - Time-mean fraction of cloud cover 235257: - avg_kx - Time-mean K index 235258: - avg_totalx - Time-mean total totals index 235261: - avg_10wdir - Time-mean 10 metre wind direction 235262: - avg_cat - Time-mean clear air turbulence (CAT) 235263: - avg_al - Time-mean forecast albedo 235269: - avg_pt - Time-mean potential temperature 235270: - avg_dis - Time-mean discharge from rivers or streams 235271: - avg_swit - Time-mean soil wetness index (total layer) 235272: - avg_swir - Time-mean soil wetness index (root zone) 235273: - avg_swil - Time-mean soil wetness index(layer) 235274: - avg_flddep - Time-mean floodplain depth 235275: - avg_fldffr - Time-mean floodplain flooded fraction 235276: - avg_fldfar - Time-mean floodplain flooded area 235277: - avg_rivfr - Time-mean river fraction 235278: - avg_rivar - Time-mean river area 235279: - avg_rivcffr - Time-mean fraction of river coverage plus river related flooding 235280: - avg_rivcfar - Time-mean area of river coverage plus river related flooding 235281: - avg_aluvp_p - Time-mean UV visible albedo for direct radiation (climatological) 235282: - avg_aluvd_p - Time-mean UV visible albedo for diffuse radiation (climatological) 235283: - avg_alnip_p - Time-mean near IR albedo for direct radiation (climatological) 235284: - avg_alnid_p - Time-mean near IR albedo for diffuse radiation (climatological) 235285: - avg_asn - Time-mean snow albedo 235286: - avg_mont - Time-mean montgomery potential 235287: - avg_cape - Time-mean convective available potential energy 235288: - avg_tcc - Time-mean total cloud cover 235289: - avg_srcon - Time-mean skin reservoir content 235290: - avg_tcioz - Time-mean total column integrated ozone 235291: - avg_vike - Time-mean total column vertically-integrated kinetic energy 235292: - avg_vithe - Time-mean total column vertically-integrated enthalpy 235293: - avg_vipie - Time-mean total column vertically-integrated potential + internal energy 235294: - avg_vipile - Time-mean total column vertically-integrated potential+internal+latent energy 235295: - avg_vitoe - Time-mean total column vertically-integrated total energy 235296: - avg_viwe - Time-mean total column vertically-integrated water enthalpy 235297: - avg_aluvpi_p - Time-mean UV visible albedo for direct radiation, isotropic component (climatological) 235298: - avg_aluvpv_p - Time-mean UV visible albedo for direct radiation, volumetric component (climatological) 235299: - avg_aluvpg_p - Time-mean UV visible albedo for direct radiation, geometric component (climatological) 235300: - avg_alnipi_p - Time-mean near IR albedo for direct radiation, isotropic component (climatological) 235301: - avg_alnipv_p - Time-mean near IR albedo for direct radiation, volumetric component (climatological) 235302: - avg_alnipg_p - Time-mean near IR albedo for direct radiation, geometric component (climatological) 235303: - avg_cin - Time-mean convective inhibition 235304: - avg_zust - Time-mean friction velocity 235305: - avg_lblt - Time-mean lake bottom temperature 235306: - avg_ltlt - Time-mean lake total layer temperature 235307: - avg_lshf - Time-mean lake shape factor 235308: - avg_lict - Time-mean lake ice surface temperature 235309: - avg_licd - Time-mean lake ice total depth 235310: - avg_dndzn - Time-mean minimum vertical gradient of refractivity inside trapping layer 235311: - avg_dndza - Time-mean mean vertical gradient of refractivity inside trapping layer 235312: - avg_dctb - Time-mean duct base height 235313: - avg_tplb - Time-mean trapping layer base height 235314: - avg_tplt - Time-mean trapping layer top height 235315: - avg_degm10l - Time-mean geometric height of -10 degrees C atmospheric isothermal level above ground 235316: - avg_cbh - Time-mean cloud base height 235317: - avg_deg0l - Time-mean geometric height of 0 degrees C atmospheric isothermal level above ground 235318: - avg_i10fg - Time-mean 10 metre wind gust 235319: - avg_rhw - Time-mean relative humidity with respect to water 235320: - avg_2rhw - Time-mean 2 metre relative humidity with respect to water 235321: - avg_capes - Time-mean convective available potential energy shear 235322: - avg_trpp - Time-mean tropopause pressure 235323: - avg_hcct - Time-mean height of convective cloud top 235324: - avg_hwbt0 - Time-mean height of zero-degree wet-bulb temperature 235325: - avg_hwbt1 - Time-mean height of one-degree wet-bulb temperature 235326: - avg_litoti - Time-mean total lightning flash density 235327: - avg_tcslw - Time-mean total column supercooled liquid water 235328: - avg_u10n - Time-mean 10 metre U-component of neutral wind 235329: - avg_v10n - Time-mean 10 metre V-component of neutral wind 235330: - avg_crr - Time-mean convective rain rate 235331: - avg_lsrr - Time-mean large scale rain rate 235332: - avg_mlcape50 - Time-mean mixed-layer CAPE in the lowest 50 hPa 235333: - avg_mlcin50 - Time-mean mixed-layer CIN in the lowest 50 hPa 235334: - avg_mlcape100 - Time-mean mixed-layer CAPE in the lowest 100 hPa 235335: - avg_mlcin100 - Time-mean mixed-layer CIN in the lowest 100 hPa 235336: - avg_mudlp - Time-mean departure level of the most unstable parcel expressed as Pressure 235337: - avg_ceil - Time-mean ceiling 235338: - avg_tcsqw - Time-mean total column integrated saturation specific humidity with respect to water 235339: - avg_sdirnswrf - Time-mean surface direct normal short-wave radiation flux 235340: - avg_cossza - Time-mean cosine of solar zenith angle 235341: - avg_fprate - Time-mean freezing rain precipitation rate 235342: - avg_vige - Time-mean total column vertically-integrated eastward geopotential flux 235343: - avg_vign - Time-mean total column vertically-integrated northward geopotential flux 235344: - avg_viwgd - Time-mean total column vertically-integrated divergence of water geopotential flux 235345: - avg_vigd - Time-mean total column vertically-integrated divergence of geopotential flux 235346: - avg_viee - Time-mean total column vertically-integrated eastward enthalpy flux 235347: - avg_vien - Time-mean total column vertically-integrated northward enthalpy flux 235348: - avg_vikee - Time-mean total column vertically-integrated eastward kinetic energy flux 235349: - avg_viken - Time-mean total column vertically-integrated northward kinetic energy flux 235350: - avg_vitee - Time-mean total column vertically-integrated eastward total energy flux 235351: - avg_viten - Time-mean total column vertically-integrated northward total energy flux 235352: - avg_vied - Time-mean total column vertically-integrated divergence of enthalpy flux 235353: - avg_viked - Time-mean total column vertically-integrated divergence of kinetic energy flux 235354: - avg_vited - Time-mean total column vertically-integrated divergence of total energy flux 235355: - avg_viwed - Time-mean total column vertically-integrated divergence of water enthalpy flux 235356: - avg_vimad - Time-mean total column vertically-integrated divergence of mass flux 235357: - avg_vimae - Time-mean total column vertically-integrated eastward mass flux 235358: - avg_viman - Time-mean total column vertically-integrated northward mass flux 235359: - avg_viwvd - Time-mean total column vertically-integrated divergence of water vapour flux 235360: - avg_viclwd - Time-mean total column vertically-integrated divergence of cloud liquid water flux 235361: - avg_viciwd - Time-mean total column vertically-integrated divergence of cloud ice water flux 235362: - avg_vird - Time-mean total column vertically-integrated divergence of rain flux 235363: - avg_visd - Time-mean total column vertically-integrated divergence of snow flux 235364: - avg_viwve - Time-mean total column vertically-integrated eastward water vapour flux 235365: - avg_viwvn - Time-mean total column vertically-integrated northward water vapour flux 235366: - avg_viclwe - Time-mean total column vertically-integrated eastward cloud liquid water flux 235367: - avg_viclwn - Time-mean total column vertically-integrated northward cloud liquid water flux 235368: - avg_viciwe - Time-mean total column vertically-integrated eastward cloud ice water flux 235369: - avg_viciwn - Time-mean total column vertically-integrated northward cloud ice water flux 235370: - avg_vire - Time-mean total column vertically-integrated eastward rain flux 235371: - avg_virn - Time-mean total column vertically-integrated northward rain flux 235372: - avg_vise - Time-mean total column vertically-integrated eastward snow flux 235373: - avg_visn - Time-mean total column vertically-integrated northward snow flux 235374: - avg_vioze - Time-mean total column vertically-integrated eastward ozone flux 235375: - avg_viozn - Time-mean total column vertically-integrated northward ozone flux 235376: - avg_viozd - Time-mean total column vertically-integrated divergence of ozone flux 235377: - avg_vions - Time-mean total column vertically-integrated net source of ozone 235378: - avg_ietssofd - Time-mean eastward turbulent surface stress due to orographic form drag 235379: - avg_intssofd - Time-mean northward turbulent surface stress due to orographic form drag 235380: - avg_ietsssr - Time-mean eastward turbulent surface stress due to surface roughness 235381: - avg_intsssr - Time-mean northward turbulent surface stress due to surface roughness 235382: - avg_visp - Time-mean visibility through precipitation 235383: - avg_licgi - Time-mean cloud-to-ground lightning flash density 235386: - avg_lshnf - Time-mean land surface heat net flux 235387: - avg_sdirnswrfcs - Time-mean surface direct normal short-wave radiation flux, clear sky 235388: - avg_10cogu - Time-mean 10 metre convective gust 235389: - avg_10tugu - Time-mean 10 metre turbulent gust 235390: - avg_h0thg - Time-mean geometric height of 0 degrees C theta level above ground 235391: - avg_h1thg - Time-mean geometric height of 1 degree C theta level above ground 235392: - avg_h1p5thg - Time-mean geometric height of 1.5 degrees C theta level above ground 235393: - avg_veg - Time-mean vegetation 235394: - avg_lai - Time-mean leaf area index 235395: - avg_srhe - Time-mean surface roughness for heat 235396: - avg_rol - Time-mean Reciprocal Obukhov length 235397: - avg_deg3l - Time-mean geometric height of 3 degrees C atmospheric isothermal level above ground 235398: - avg_rivsto - Time-mean river storage of water 235399: - avg_fldsto - Time-mean floodplain storage of water 235400: - avg_rivdph - Time-mean river depth 235401: - avg_rivout - Time-mean river outflow of water 235402: - avg_fldout - Time-mean floodplain outflow of water 235403: - avg_pthflw - Time-mean floodpath outflow of water 235404: - avg_sdifswrfcs - Time-mean surface diffuse short-wave radiation flux, clear sky 235405: - avg_vswrz - Time-mean volumetric soil moisture (root zone) 235406: - avg_lwcs - Time-mean liquid water content in snow pack 235407: - avg_mucin - Time-mean most-unstable CIN 235408: - avg_crwc_conv - Time-mean specific rain water content (convective) 235409: - avg_cswc_conv - Time-mean specific snow water content (convective) 235410: - avg_mld - Time-mean mixed layer depth 235411: - avg_cur - Time-mean urban cover 236386: - acc_lshnf - Time-integrated land surface heat net flux 236387: - acc_sdirnswrfcs - Time-integrated surface direct normal short-wave radiation flux, clear sky 237001: - max_ttswr - Time-maximum temperature tendency due to short-wave radiation 237002: - max_ttlwr - Time-maximum temperature tendency due to long-wave radiation 237003: - max_ttswrcs - Time-maximum temperature tendency due to short wave radiation, clear sky 237004: - max_ttlwrcs - Time-maximum temperature tendency due to long-wave radiation, clear sky 237005: - max_ttpm - Time-maximum temperature tendency due to parametrisations 237006: - max_qtpm - Time-maximum specific humidity tendency due to parametrisations 237007: - max_utpm - Time-maximum eastward wind tendency due to parametrisations 237008: - max_vtpm - Time-maximum northward wind tendency due to parametrisations 237009: - max_umf - Time-maximum updraught mass flux 237010: - max_dmf - Time-maximum downdraught mass flux 237011: - max_udr - Time-maximum updraught detrainment rate 237012: - max_ddr - Time-maximum downdraught detrainment rate 237013: - max_tpf - Time-maximum total precipitation flux 237014: - max_tdch - Time-maximum turbulent diffusion coefficient for heat 237022: - max_parcsf - Time-maximum surface photosynthetically active radiation flux, clear sky 237023: - max_esrwe - Time-maximum snow evaporation rate water equivalent 237024: - max_smr - Time-maximum snow melt rate 237025: - max_imagss - Time-maximum magnitude of turbulent surface stress 237026: - max_ilspf - Time-maximum large-scale precipitation fraction 237027: - max_sduvrf - Time-maximum surface downward UV radiation flux 237028: - max_sparf - Time-maximum surface photosynthetically active radiation flux 237029: - max_lsprate - Time-maximum large-scale precipitation rate 237030: - max_cpr - Time-maximum convective precipitation rate 237031: - max_tsrwe - Time-maximum total snowfall rate water equivalent 237032: - max_ibld - Time-maximum boundary layer dissipation 237033: - max_ishf - Time-maximum surface sensible heat flux 237034: - max_slhtf - Time-maximum surface latent heat flux 237035: - max_sdswrf - Time-maximum surface downward short-wave radiation flux 237036: - max_sdlwrf - Time-maximum surface downward long-wave radiation flux 237037: - max_snswrf - Time-maximum surface net short-wave radiation flux 237038: - max_snlwrf - Time-maximum surface net long-wave radiation flux 237039: - max_tnswrf - Time-maximum top net short-wave radiation flux 237040: - max_tnlwrf - Time-maximum top net long-wave radiation flux 237041: - max_iews - Time-maximum eastward turbulent surface stress 237042: - max_inss - Time-maximum northward turbulent surface stress 237043: - max_ie - Time-maximum moisture flux 237045: - max_iegwss - Time-maximum eastward gravity wave surface stress 237046: - max_ingwss - Time-maximum northward gravity wave surface stress 237047: - max_igwd - Time-maximum gravity wave dissipation 237048: - max_rorwe - Time-maximum runoff rate water equivalent (surface plus subsurface) 237049: - max_tnswrfcs - Time-maximum top net short-wave radiation flux, clear sky 237050: - max_tnlwrfcs - Time-maximum top net long-wave radiation flux, clear sky 237051: - max_snswrfcs - Time-maximum surface net short-wave radiation flux, clear sky 237052: - max_snlwrfcs - Time-maximum surface net long-wave radiation flux, clear sky 237053: - max_tdswrf - Time mean top downward short-wave radiation flux 237054: - max_vimdf - Time-maximum total column vertically-integrated moisture divergence flux 237055: - max_tprate - Time-maximum total precipitation rate 237056: - max_csfr - Time-maximum convective snowfall rate water equivalent 237057: - max_lssfr - Time-maximum large scale snowfall rate water equivalent 237058: - max_sdirswrf - Time-maximum surface direct short-wave radiation flux 237059: - max_sdirswrfcs - Time-maximum surface direct short-wave radiation flux, clear sky 237062: - max_fco2nee - Time-maximum carbon dioxide net ecosystem exchange flux 237063: - max_fco2gpp - Time-maximum carbon dioxide gross primary production flux 237064: - max_fco2rec - Time-maximum carbon dioxide ecosystem respiration flux 237068: - max_sdswrfcs - Time-maximum surface downward short-wave radiation flux, clear sky 237069: - max_sdlwrfcs - Time-maximum surface downward long-wave radiation flux, clear sky 237070: - max_pevr - Time-maximum potential evaporation rate 237077: - max_vsw - Time-maximum volumetric soil moisture 237078: - max_sd - Time-maximum snow depth water equivalent 237079: - max_skt - Time-maximum skin temperature 237080: - max_rsn - Time-maximum snow density 237083: - max_ci - Time-maximum sea ice area fraction 237084: - max_sst - Time-maximum sea surface temperature 237085: - max_lai_lv - Time-maximum leaf area index, low vegetation 237086: - max_lai_hv - Time-maximum leaf area index, high vegetation 237087: - max_tclw - Time-maximum total column cloud liquid water 237088: - max_tciw - Time-maximum total column cloud ice water 237089: - max_2sh - Time-maximum 2 metre specific humidity 237090: - max_lmlt - Time-maximum lake mix-layer temperature 237091: - max_lmld - Time-maximum lake mix-layer depth 237092: - max_2r - Time-maximum 2 metre relative humidity 237093: - max_fscov - Time-maximum fraction of snow cover 237094: - max_sot - Time-maximum soil temperature 237097: - max_ws - Time-maximum wind speed 237098: - max_pres - Time-maximum pressure 237099: - max_chnk - Time-maximum charnock 237100: - max_pv - Time-maximum potential vorticity 237101: - max_crwc - Time-maximum specific rain water content 237102: - max_cswc - Time-maximum specific snow water content 237103: - max_etadot - Time-maximum eta-coordinate vertical velocity 237105: - max_vis - Time-maximum visibility 237106: - max_wdir - Time-maximum wind direction 237107: - max_tcsw - Time-maximum total column snow water 237108: - max_lcc - Time-maximum low cloud cover 237109: - max_mcc - Time-maximum medium cloud cover 237110: - max_hcc - Time-maximum high cloud cover 237111: - max_tcrw - Time-maximum total column rain water 237117: - max_mucape - Time-maximum most-unstable CAPE 237120: - max_tcolg - Time-maximum total column vertically-integrated graupel (snow pellets) 237129: - max_z - Time-maximum geopotential 237130: - max_t - Time-maximum temperature 237131: - max_u - Time-maximum u component of wind 237132: - max_v - Time-maximum v component of wind 237133: - max_q - Time-maximum specific humidity 237134: - max_sp - Time-maximum surface pressure 237135: - max_w - Time-maximum vertical velocity 237136: - max_tcw - Time-maximum total column water 237137: - max_tcwv - Time-maximum total column vertically-integrated water vapour 237138: - max_vo - Time-maximum vorticity (relative) 237151: - max_msl - Time-maximum mean sea level pressure 237152: - max_lnsp - Time-maximum logarithm of surface pressure 237155: - max_d - Time-maximum divergence 237157: - max_r - Time-maximum relative humidity 237159: - max_blh - Time-maximum boundary layer height 237165: - max_10u - Time-maximum 10 metre U wind component 237166: - max_10v - Time-maximum 10 metre V wind component 237167: - max_2t - Time-maximum 2 metre temperature 237168: - max_2d - Time-maximum 2 metre dewpoint temperature 237189: - max_suns - Time-maximum sunshine 237203: - max_o3 - Time-maximum ozone mass mixing ratio 237207: - max_10si - Time-maximum 10 metre wind speed 237238: - max_tsn - Time-maximum temperature of snow layer 237244: - max_fsr - Time-maximum forecast surface roughness 237245: - max_flsr - Time-maximum forecast logarithm of surface roughness for heat 237246: - max_clwc - Time-maximum specific cloud liquid water content 237247: - max_ciwc - Time-maximum specific cloud ice water content 237248: - max_cc - Time-maximum fraction of cloud cover 237257: - max_kx - Time-maximum k index 237258: - max_totalx - Time-maximum total totals index 237261: - max_10wdir - Time-maximum 10 metre wind direction 237262: - max_cat - Time-maximum clear air turbulence (CAT) 237263: - max_al - Time-maximum forecast albedo 237269: - max_pt - Time-maximum potential temperature 237281: - max_aluvp_p - Time-maximum UV visible albedo for direct radiation (climatological) 237282: - max_aluvd_p - Time-maximum UV visible albedo for diffuse radiation (climatological) 237283: - max_alnip_p - Time-maximum near IR albedo for direct radiation (climatological) 237284: - max_alnid_p - Time-maximum near IR albedo for diffuse radiation (climatological) 237285: - max_asn - Time-maximum snow albedo 237286: - max_mont - Time-maximum montgomery potential 237287: - max_cape - Time-maximum convective available potential energy 237288: - max_tcc - Time-maximum total cloud cover 237289: - max_srcon - Time-maximum skin reservoir content 237290: - max_tcioz - Time-maximum total column integrated ozone 237291: - max_vike - Time-maximum total column vertically-integrated kinetic energy 237292: - max_vithe - Time-maximum total column vertically-integrated enthalpy 237293: - max_vipie - Time-maximum total column vertically-integrated potential + internal energy 237294: - max_vipile - Time-maximum total column vertically-integrated potential+internal+latent energy 237295: - max_vitoe - Time-maximum total column vertically-integrated total energy 237296: - max_viwe - Time-maximum total column vertically-integrated water enthalpy 237297: - max_aluvpi_p - Time-maximum UV visible albedo for direct radiation, isotropic component (climatological) 237298: - max_aluvpv_p - Time-maximum UV visible albedo for direct radiation, volumetric component (climatological) 237299: - max_aluvpg_p - Time-maximum UV visible albedo for direct radiation, geometric component (climatological) 237300: - max_alnipi_p - Time-maximum near IR albedo for direct radiation, isotropic component (climatological) 237301: - max_alnipv_p - Time-maximum near IR albedo for direct radiation, volumetric component (climatological) 237302: - max_alnipg_p - Time-maximum near IR albedo for direct radiation, geometric component (climatological) 237303: - max_cin - Time-maximum convective inhibition 237304: - max_zust - Time-maximum friction velocity 237305: - max_lblt - Time-maximum lake bottom temperature 237306: - max_ltlt - Time-maximum lake total layer temperature 237307: - max_lshf - Time-maximum lake shape factor 237308: - max_lict - Time-maximum lake ice surface temperature 237309: - max_licd - Time-maximum lake ice total depth 237310: - max_dndzn - Time-maximum minimum vertical gradient of refractivity inside trapping layer 237311: - max_dndza - Time-maximum mean vertical gradient of refractivity inside trapping layer 237312: - max_dctb - Time-maximum duct base height 237313: - max_tplb - Time-maximum trapping layer base height 237314: - max_tplt - Time-maximum trapping layer top height 237315: - max_degm10l - Time-maximum geometric height of -10 degrees C atmospheric isothermal level above ground 237316: - max_cbh - Time-maximum cloud base height 237317: - max_deg0l - Time-maximum geometric height of 0 degrees C atmospheric isothermal level above ground 237318: - max_i10fg - Time-maximum 10 metre wind gust 237319: - max_rhw - Time-maximum relative humidity with respect to water 237320: - max_2rhw - Time-maximum 2 metre relative humidity with respect to water 237321: - max_capes - Time-maximum convective available potential energy shear 237322: - max_trpp - Time-maximum tropopause pressure 237323: - max_hcct - Time-maximum height of convective cloud top 237324: - max_hwbt0 - Time-maximum height of zero-degree wet-bulb temperature 237325: - max_hwbt1 - Time-maximum height of one-degree wet-bulb temperature 237326: - max_litoti - Time-maximum total lightning flash density 237327: - max_tcslw - Time-maximum total column supercooled liquid water 237328: - max_u10n - Time-maximum 10 metre U-component of neutral wind 237329: - max_v10n - Time-maximum 10 metre V-component of neutral wind 237330: - max_crr - Time-maximum convective rain rate 237331: - max_lsrr - Time-maximum large scale rain rate 237332: - max_mlcape50 - Time-maximum mixed-layer CAPE in the lowest 50 hPa 237333: - max_mlcin50 - Time-maximum mixed-layer CIN in the lowest 50 hPa 237334: - max_mlcape100 - Time-maximum mixed-layer CAPE in the lowest 100 hPa 237335: - max_mlcin100 - Time-maximum mixed-layer CIN in the lowest 100 hPa 237336: - max_mudlp - Time-maximum departure level of the most unstable parcel expressed as Pressure 237337: - max_ceil - Time-maximum ceiling 237338: - max_tcsqw - Time-maximum total column integrated saturation specific humidity with respect to water 237339: - max_sdirnswrf - Time-maximum surface direct normal short-wave radiation flux 237340: - max_cossza - Time-maximum cosine of solar zenith angle 237341: - max_fprate - Time-maximum freezing rain precipitation rate 237342: - max_vige - Time-maximum total column vertically-integrated eastward geopotential flux 237343: - max_vign - Time-maximum total column vertically-integrated northward geopotential flux 237344: - max_viwgd - Time-maximum total column vertically-integrated divergence of water geopotential flux 237345: - max_vigd - Time-maximum total column vertically-integrated divergence of geopotential flux 237346: - max_viee - Time-maximum total column vertically-integrated eastward enthalpy flux 237347: - max_vien - Time-maximum total column vertically-integrated northward enthalpy flux 237348: - max_vikee - Time-maximum total column vertically-integrated eastward kinetic energy flux 237349: - max_viken - Time-maximum total column vertically-integrated northward kinetic energy flux 237350: - max_vitee - Time-maximum total column vertically-integrated eastward total energy flux 237351: - max_viten - Time-maximum total column vertically-integrated northward total energy flux 237352: - max_vied - Time-maximum total column vertically-integrated divergence of enthalpy flux 237353: - max_viked - Time-maximum total column vertically-integrated divergence of kinetic energy flux 237354: - max_vited - Time-maximum total column vertically-integrated divergence of total energy flux 237355: - max_viwed - Time-maximum total column vertically-integrated divergence of water enthalpy flux 237356: - max_vimad - Time-maximum total column vertically-integrated divergence of mass flux 237357: - max_vimae - Time-maximum total column vertically-integrated eastward mass flux 237358: - max_viman - Time-maximum total column vertically-integrated northward mass flux 237359: - max_viwvd - Time-maximum total column vertically-integrated divergence of water vapour flux 237360: - max_viclwd - Time-maximum total column vertically-integrated divergence of cloud liquid water flux 237361: - max_viciwd - Time-maximum total column vertically-integrated divergence of cloud ice water flux 237362: - max_vird - Time-maximum total column vertically-integrated divergence of rain flux 237363: - max_visd - Time-maximum total column vertically-integrated divergence of snow flux 237364: - max_viwve - Time-maximum total column vertically-integrated eastward water vapour flux 237365: - max_viwvn - Time-maximum total column vertically-integrated northward water vapour flux 237366: - max_viclwe - Time-maximum total column vertically-integrated eastward cloud liquid water flux 237367: - max_viclwn - Time-maximum total column vertically-integrated northward cloud liquid water flux 237368: - max_viciwe - Time-maximum total column vertically-integrated eastward cloud ice water flux 237369: - max_viciwn - Time-maximum total column vertically-integrated northward cloud ice water flux 237370: - max_vire - Time-maximum total column vertically-integrated eastward rain flux 237371: - max_virn - Time-maximum total column vertically-integrated northward rain flux 237372: - max_vise - Time-maximum total column vertically-integrated eastward snow flux 237373: - max_visn - Time-maximum total column vertically-integrated northward snow flux 237374: - max_vioze - Time-maximum total column vertically-integrated eastward ozone flux 237375: - max_viozn - Time-maximum total column vertically-integrated northward ozone flux 237376: - max_viozd - Time-maximum total column vertically-integrated divergence of ozone flux 237377: - max_vions - Time-maximum total column vertically-integrated net source of ozone 237378: - max_ietssofd - Time-maximum eastward turbulent surface stress due to orographic form drag 237379: - max_intssofd - Time-maximum northward turbulent surface stress due to orographic form drag 237380: - max_ietsssr - Time-maximum eastward turbulent surface stress due to surface roughness 237381: - max_intsssr - Time-maximum northward turbulent surface stress due to surface roughness 237382: - max_visp - Time-maximum visibility through precipitation 237383: - max_licgi - Time-maximum cloud-to-ground lightning flash density 237384: - max_10efg - Time-maximum 10 metre eastward wind gust 237385: - max_10nfg - Time-maximum 10 metre northward wind gust 237386: - max_lshnf - Time-maximum land surface heat net flux 237387: - max_sdirnswrfcs - Time-maximum surface direct normal short-wave radiation flux, clear sky 237388: - max_10cogu - Time-maximum 10 metre convective gust 237389: - max_10tugu - Time-maximum 10 metre turbulent gust 237390: - max_h0thg - Time-maximum geometric height of 0 degrees C theta level above ground 237391: - max_h1thg - Time-maximum geometric height of 1 degree C theta level above ground 237392: - max_h1p5thg - Time-maximum geometric height of 1.5 degrees C theta level above ground 237393: - max_veg - Time-maximum vegetation 237394: - max_lai - Time-maximum leaf area index 237395: - max_srhe - Time-maximum surface roughness for heat 237396: - max_rol - Time-maximum Reciprocal Obukhov length 237397: - max_deg3l - Time-maximum geometric height of 3 degrees C atmospheric isothermal level above ground 237404: - max_sdifswrfcs - Time-maximum surface diffuse short-wave radiation flux, clear sky 237405: - max_vswrz - Time-maximum volumetric soil moisture (root zone) 237406: - max_lwcs - Time-maximum liquid water content in snow pack 237407: - max_mucin - Time-maximum most-unstable CIN 237408: - max_crwc_conv - Time-maximum specific rain water content (convective) 237409: - max_cswc_conv - Time-maximum specific snow water content (convective) 237410: - max_mld - Time-maximum mixed layer depth 237411: - max_cur - Time-maximum urban cover 238001: - min_ttswr - Time-minimum temperature tendency due to short-wave radiation 238002: - min_ttlwr - Time-minimum temperature tendency due to long-wave radiation 238003: - min_ttswrcs - Time-minimum temperature tendency due to short wave radiation, clear sky 238004: - min_ttlwrcs - Time-minimum temperature tendency due to long-wave radiation, clear sky 238005: - min_ttpm - Time-minimum temperature tendency due to parametrisations 238006: - min_qtpm - Time-minimum specific humidity tendency due to parametrisations 238007: - min_utpm - Time-minimum eastward wind tendency due to parametrisations 238008: - min_vtpm - Time-minimum northward wind tendency due to parametrisations 238009: - min_umf - Time-minimum updraught mass flux 238010: - min_dmf - Time-minimum downdraught mass flux 238011: - min_udr - Time-minimum updraught detrainment rate 238012: - min_ddr - Time-minimum downdraught detrainment rate 238013: - min_tpf - Time-minimum total precipitation flux 238014: - min_tdch - Time-minimum turbulent diffusion coefficient for heat 238022: - min_parcsf - Time-minimum surface photosynthetically active radiation flux, clear sky 238023: - min_esrwe - Time-minimum snow evaporation rate 238024: - min_smr - Time-minimum snowmelt rate 238025: - min_imagss - Time-minimum magnitude of turbulent surface stress 238026: - min_ilspf - Time-minimum large-scale precipitation fraction 238027: - min_sduvrf - Time-minimum surface downward UV radiation flux 238028: - min_sparf - Time-minimum surface photosynthetically active radiation flux 238029: - min_lsprate - Time-minimum large-scale precipitation rate 238030: - min_cpr - Time-minimum convective precipitation rate 238031: - min_tsrwe - Time-minimum snowfall rate 238032: - min_ibld - Time-minimum boundary layer dissipation 238033: - min_ishf - Time-minimum surface sensible heat flux 238034: - min_slhtf - Time-minimum surface latent heat flux 238035: - min_sdswrf - Time-minimum surface downward short-wave radiation flux 238036: - min_sdlwrf - Time-minimum surface downward long-wave radiation flux 238037: - min_snswrf - Time-minimum surface net short-wave radiation flux 238038: - min_snlwrf - Time-minimum surface net long-wave radiation flux 238039: - min_tnswrf - Time-minimum top net short-wave radiation flux 238040: - min_tnlwrf - Time-minimum top net long-wave radiation flux 238041: - min_iews - Time-minimum eastward turbulent surface stress 238042: - min_inss - Time-minimum northward turbulent surface stress 238043: - min_ie - Time-minimum evaporation rate 238045: - min_iegwss - Time-minimum eastward gravity wave surface stress 238046: - min_ingwss - Time-minimum northward gravity wave surface stress 238047: - min_igwd - Time-minimum gravity wave dissipation 238048: - min_rorwe - Time-minimum runoff rate 238049: - min_tnswrfcs - Time-minimum top net short-wave radiation flux, clear sky 238050: - min_tnlwrfcs - Time-minimum top net long-wave radiation flux, clear sky 238051: - min_snswrfcs - Time-minimum surface net short-wave radiation flux, clear sky 238052: - min_snlwrfcs - Time-minimum surface net long-wave radiation flux, clear sky 238053: - min_tdswrf - Time-minimum top downward short-wave radiation flux 238054: - min_vimdf - Time-minimum vertically integrated moisture divergence 238055: - min_tprate - Time-minimum total precipitation rate 238056: - min_csfr - Time-minimum convective snowfall rate water equivalent 238057: - min_lssfr - Time-minimum large scale snowfall rate water equivalent 238058: - min_sdirswrf - Time-minimum surface direct short-wave radiation flux 238059: - min_sdirswrfcs - Time-minimum surface direct short-wave radiation flux, clear sky 238062: - min_fco2nee - Time-minimum carbon dioxide net ecosystem exchange flux 238063: - min_fco2gpp - Time-minimum carbon dioxide gross primary production flux 238064: - min_fco2rec - Time-minimum carbon dioxide ecosystem respiration flux 238068: - min_sdswrfcs - Time-minimum surface downward short-wave radiation flux, clear sky 238069: - min_sdlwrfcs - Time-minimum surface downward long-wave radiation flux, clear sky 238070: - min_pevr - Time-minimum potential evaporation rate 238077: - min_vsw - Time-minimum volumetric soil moisture 238078: - min_sd - Time-minimum snow depth water equivalent 238079: - min_skt - Time-minimum skin temperature 238080: - min_rsn - Time-minimum snow density 238083: - min_ci - Time-minimum sea ice area fraction 238084: - min_sst - Time-minimum sea surface temperature 238085: - min_lai_lv - Time-minimum leaf area index, low vegetation 238086: - min_lai_hv - Time-minimum leaf area index, high vegetation 238087: - min_tclw - Time-minimum total column cloud liquid water 238088: - min_tciw - Time-minimum total column cloud ice water 238089: - min_2sh - Time-minimum 2 metre specific humidity 238090: - min_lmlt - Time-minimum lake mix-layer temperature 238091: - min_lmld - Time-minimum lake mix-layer depth 238092: - min_2r - Time-minimum 2 metre relative humidity 238093: - min_fscov - Time-minimum fraction of snow cover 238094: - min_sot - Time-minimum soil temperature 238097: - min_ws - Time-minimum wind speed 238098: - min_pres - Time-minimum pressure 238099: - min_chnk - Time-minimum charnock 238100: - min_pv - Time-minimum potential vorticity 238101: - min_crwc - Time-minimum specific rain water content 238102: - min_cswc - Time-minimum specific snow water content 238103: - min_etadot - Time-minimum eta-coordinate vertical velocity 238105: - min_vis - Time-minimum visibility 238106: - min_wdir - Time-minimum wind direction 238107: - min_tcsw - Time-minimum total column snow water 238108: - min_lcc - Time-minimum low cloud cover 238109: - min_mcc - Time-minimum medium cloud cover 238110: - min_hcc - Time-minimum high cloud cover 238111: - min_tcrw - Time-minimum total column rain water 238117: - min_mucape - Time-minimum most-unstable CAPE 238120: - min_tcolg - Time-minimum total column vertically-integrated graupel (snow pellets) 238129: - min_z - Time-minimum geopotential 238130: - min_t - Time-minimum temperature 238131: - min_u - Time-minimum u component of wind 238132: - min_v - Time-minimum v component of wind 238133: - min_q - Time-minimum specific humidity 238134: - min_sp - Time-minimum surface pressure 238135: - min_w - Time-minimum vertical velocity 238136: - min_tcw - Time-minimum total column water 238137: - min_tcwv - Time-minimum total column vertically-integrated water vapour 238138: - min_vo - Time-minimum vorticity (relative) 238151: - min_msl - Time-minimum mean sea level pressure 238152: - min_lnsp - Time-minimum logarithm of surface pressure 238155: - min_d - Time-minimum divergence 238157: - min_r - Time-minimum relative humidity 238159: - min_blh - Time-minimum boundary layer height 238165: - min_10u - Time-minimum 10 metre U wind component 238166: - min_10v - Time-minimum 10 metre V wind component 238167: - min_2t - Time-minimum 2 metre temperature 238168: - min_2d - Time-minimum 2 metre dewpoint temperature 238189: - min_suns - Time-minimum sunshine 238203: - min_o3 - Time-minimum ozone mass mixing ratio 238207: - min_10si - Time-minimum 10 metre wind speed 238238: - min_tsn - Time-minimum temperature of snow layer 238244: - min_fsr - Time-minimum forecast surface roughness 238245: - min_flsr - Time-minimum forecast logarithm of surface roughness for heat 238246: - min_clwc - Time-minimum specific cloud liquid water content 238247: - min_ciwc - Time-minimum specific cloud ice water content 238248: - min_cc - Time-minimum fraction of cloud cover 238257: - min_kx - Time-minimum k index 238258: - min_totalx - Time-minimum total totals index 238261: - min_10wdir - Time-minimum 10 metre wind direction 238262: - min_cat - Time-minimum clear air turbulence (CAT) 238263: - min_al - Time-minimum forecast albedo 238269: - min_pt - Time-minimum potential temperature 238281: - min_aluvp_p - Time-minimum UV visible albedo for direct radiation (climatological) 238282: - min_aluvd_p - Time-minimum UV visible albedo for diffuse radiation (climatological) 238283: - min_alnip_p - Time-minimum near IR albedo for direct radiation (climatological) 238284: - min_alnid_p - Time-minimum near IR albedo for diffuse radiation (climatological) 238285: - min_asn - Time-minimum snow albedo 238286: - min_mont - Time-minimum montgomery potential 238287: - min_cape - Time-minimum convective available potential energy 238288: - min_tcc - Time-minimum total cloud cover 238289: - min_srcon - Time-minimum skin reservoir content 238290: - min_tcioz - Time-minimum total column integrated ozone 238291: - min_vike - Time-minimum total column vertically-integrated kinetic energy 238292: - min_vithe - Time-minimum total column vertically-integrated enthalpy 238293: - min_vipie - Time-minimum total column vertically-integrated potential + internal energy 238294: - min_vipile - Time-minimum vertical integral of potential+internal+latent energy 238295: - min_vitoe - Time-minimum total column vertically-integrated total energy 238296: - min_viwe - Time-minimum total column vertically-integrated water enthalpy 238297: - min_aluvpi_p - Time-minimum UV visible albedo for direct radiation, isotropic component (climatological) 238298: - min_aluvpv_p - Time-minimum UV visible albedo for direct radiation, volumetric component (climatological) 238299: - min_aluvpg_p - Time-minimum UV visible albedo for direct radiation, geometric component (climatological) 238300: - min_alnipi_p - Time-minimum near IR albedo for direct radiation, isotropic component (climatological) 238301: - min_alnipv_p - Time-minimum near IR albedo for direct radiation, volumetric component (climatological) 238302: - min_alnipg_p - Time-minimum near IR albedo for direct radiation, geometric component (climatological) 238303: - min_cin - Time-minimum convective inhibition 238304: - min_zust - Time-minimum friction velocity 238305: - min_lblt - Time-minimum lake bottom temperature 238306: - min_ltlt - Time-minimum lake total layer temperature 238307: - min_lshf - Time-minimum lake shape factor 238308: - min_lict - Time-minimum lake ice surface temperature 238309: - min_licd - Time-minimum lake ice total depth 238310: - min_dndzn - Time-minimum minimum vertical gradient of refractivity inside trapping layer 238311: - min_dndza - Time-minimum mean vertical gradient of refractivity inside trapping layer 238312: - min_dctb - Time-minimum duct base height 238313: - min_tplb - Time-minimum trapping layer base height 238314: - min_tplt - Time-minimum trapping layer top height 238315: - min_degm10l - Time-minimum geometric height of -10 degrees C atmospheric isothermal level above ground 238316: - min_cbh - Time-minimum cloud base height 238317: - min_deg0l - Time-minimum geometric height of 0 degrees C atmospheric isothermal level above ground 238318: - min_i10fg - Time-minimum 10 metre wind gust 238319: - min_rhw - Time-minimum relative humidity with respect to water 238320: - min_2rhw - Time-minimum 2 metre relative humidity with respect to water 238321: - min_capes - Time-minimum convective available potential energy shear 238322: - min_trpp - Time-minimum tropopause pressure 238323: - min_hcct - Time-minimum height of convective cloud top 238324: - min_hwbt0 - Time-minimum height of zero-degree wet-bulb temperature 238325: - min_hwbt1 - Time-minimum height of one-degree wet-bulb temperature 238326: - min_litoti - Time-minimum total lightning flash density 238327: - min_tcslw - Time-minimum total column supercooled liquid water 238328: - min_u10n - Time-minimum 10 metre U-component of neutral wind 238329: - min_v10n - Time-minimum 10 metre V-component of neutral wind 238330: - min_crr - Time-minimum convective rain rate 238331: - min_lsrr - Time-minimum large scale rain rate 238332: - min_mlcape50 - Time-minimum mixed-layer CAPE in the lowest 50 hPa 238333: - min_mlcin50 - Time-minimum mixed-layer CIN in the lowest 50 hPa 238334: - min_mlcape100 - Time-minimum mixed-layer CAPE in the lowest 100 hPa 238335: - min_mlcin100 - Time-minimum mixed-layer CIN in the lowest 100 hPa 238336: - min_mudlp - Time-minimum departure level of the most unstable parcel expressed as Pressure 238337: - min_ceil - Time-minimum ceiling 238338: - min_tcsqw - Time-minimum total column integrated saturation specific humidity with respect to water 238339: - min_sdirnswrf - Time-minimum direct solar radiation flux 238340: - min_cossza - Time-minimum cosine of solar zenith angle 238341: - min_fprate - Time-minimum freezing rain rate water equivalent 238342: - min_vige - Time-minimum total column vertically-integrated eastward geopotential flux 238343: - min_vign - Time-minimum total column vertically-integrated northward geopotential flux 238344: - min_viwgd - Time-minimum total column vertically-integrated divergence of water geopotential flux 238345: - min_vigd - Time-minimum total column vertically-integrated divergence of geopotential flux 238346: - min_viee - Time-minimum total column vertically-integrated eastward enthalpy flux 238347: - min_vien - Time-minimum total column vertically-integrated northward enthalpy flux 238348: - min_vikee - Time-minimum total column vertically-integrated eastward kinetic energy flux 238349: - min_viken - Time-minimum total column vertically-integrated northward kinetic energy flux 238350: - min_vitee - Time-minimum total column vertically-integrated eastward total energy flux 238351: - min_viten - Time-minimum total column vertically-integrated northward total energy flux 238352: - min_vied - Time-minimum total column vertically-integrated divergence of enthalpy flux 238353: - min_viked - Time-minimum total column vertically-integrated divergence of kinetic energy flux 238354: - min_vited - Time-minimum total column vertically-integrated divergence of total energy flux 238355: - min_viwed - Time-minimum total column vertically-integrated divergence of water enthalpy flux 238356: - min_vimad - Time-minimum vertically integrated divergence of mass flux 238357: - min_vimae - Time-minimum vertically integrated eastward mass flux 238358: - min_viman - Time-minimum vertically integrated northward mass flux 238359: - min_viwvd - Time-minimum vertically integrated divergence of water vapour flux 238360: - min_viclwd - Time-minimum vertically integrated divergence of cloud liquid water flux 238361: - min_viciwd - Time-minimum vertically integrated divergence of cloud ice water flux 238362: - min_vird - Time-minimum vertically integrated divergence of rain flux 238363: - min_visd - Time-minimum vertically integrated divergence of snow flux 238364: - min_viwve - Time-minimum vertically integrated eastward water vapour flux 238365: - min_viwvn - Time-minimum vertically integrated northward water vapour flux 238366: - min_viclwe - Time-minimum vertically integrated eastward cloud liquid water flux 238367: - min_viclwn - Time-minimum vertically integrated northward cloud liquid water flux 238368: - min_viciwe - Time-minimum vertically integrated eastward cloud ice water flux 238369: - min_viciwn - Time-minimum vertically integrated northward cloud ice water flux 238370: - min_vire - Time-minimum vertically integrated eastward rain flux 238371: - min_virn - Time-minimum vertically integrated northward rain flux 238372: - min_vise - Time-minimum vertically integrated eastward snow flux 238373: - min_visn - Time-minimum vertically integrated northward snow flux 238374: - min_vioze - Time-minimum vertically integrated eastward ozone flux 238375: - min_viozn - Time-minimum vertically integrated northward ozone flux 238376: - min_viozd - Time-minimum vertically integrated divergence of ozone flux 238377: - min_vions - Time-minimum vertically integrated net source of ozone 238378: - min_ietssofd - Time-minimum eastward turbulent surface stress due to orographic form drag 238379: - min_intssofd - Time-minimum northward turbulent surface stress due to orographic form drag 238380: - min_ietsssr - Time-minimum eastward turbulent surface stress due to surface roughness 238381: - min_intsssr - Time-minimum northward turbulent surface stress due to surface roughness 238382: - min_visp - Time-minimum visibility through precipitation 238383: - min_licgi - Time-minimum cloud-to-ground lightning flash density 238386: - min_lshnf - Time-minimum land surface heat net flux 238387: - min_sdirnswrfcs - Time-minimum surface direct normal short-wave radiation flux, clear sky 238388: - min_10cogu - Time-minimum 10 metre convective gust 238389: - min_10tugu - Time-minimum 10 metre turbulent gust 238390: - min_h0thg - Time-minimum geometric height of 0 degrees C theta level above ground 238391: - min_h1thg - Time-minimum geometric height of 1 degree C theta level above ground 238392: - min_h1p5thg - Time-minimum geometric height of 1.5 degrees C theta level above ground 238393: - min_veg - Time-minimum vegetation 238394: - min_lai - Time-minimum leaf area index 238395: - min_srhe - Time-minimum surface roughness for heat 238396: - min_rol - Time-minimum Reciprocal Obukhov length 238397: - min_deg3l - Time-minimum geometric height of 3 degrees C atmospheric isothermal level above ground 238404: - min_sdifswrfcs - Time-minimum surface diffuse short-wave radiation flux, clear sky 238405: - min_vswrz - Time-minimum volumetric soil moisture (root zone) 238406: - min_lwcs - Time-minimum liquid water content in snow pack 238407: - min_mucin - Time-minimum most-unstable CIN 238408: - min_crwc_conv - Time-minimum specific rain water content (convective) 238409: - min_cswc_conv - Time-minimum specific snow water content (convective) 238410: - min_mld - Time-minimum mixed layer depth 238411: - min_cur - Time-minimum urban cover 239001: - std_ttswr - Time-standard-deviation temperature tendency due to short-wave radiation 239002: - std_ttlwr - Time-standard-deviation temperature tendency due to long-wave radiation 239003: - std_ttswrcs - Time-standard-deviation temperature tendency due to short wave radiation, clear sky 239004: - std_ttlwrcs - Time-standard-deviation temperature tendency due to long-wave radiation, clear sky 239005: - std_ttpm - Time-standard-deviation temperature tendency due to parametrisations 239006: - std_qtpm - Time-standard-deviation specific humidity tendency due to parametrisations 239007: - std_utpm - Time-standard-deviation eastward wind tendency due to parametrisations 239008: - std_vtpm - Time-standard-deviation northward wind tendency due to parametrisations 239009: - std_umf - Time-standard-deviation updraught mass flux 239010: - std_dmf - Time-standard-deviation downdraught mass flux 239011: - std_udr - Time-standard-deviation updraught detrainment rate 239012: - std_ddr - Time-standard-deviation downdraught detrainment rate 239013: - std_tpf - Time-standard-deviation total precipitation flux 239014: - std_tdch - Time-standard-deviation turbulent diffusion coefficient for heat 239022: - std_parcsf - Time-standard-deviation surface photosynthetically active radiation flux, clear sky 239023: - std_esrwe - Time-standard-deviation snow evaporation rate 239024: - std_smr - Time-standard-deviation snowmelt rate 239025: - std_imagss - Time-standard-deviation magnitude of turbulent surface stress 239026: - std_ilspf - Time-standard-deviation large-scale precipitation fraction 239027: - std_sduvrf - Time-standard-deviation surface downward UV radiation flux 239028: - std_sparf - Time-standard-deviation surface photosynthetically active radiation flux 239029: - std_lsprate - Time-standard-deviation large-scale precipitation rate 239030: - std_cpr - Time-standard-deviation convective precipitation rate 239031: - std_tsrwe - Time-standard-deviation snowfall rate 239032: - std_ibld - Time-standard-deviation boundary layer dissipation 239033: - std_ishf - Time-standard-deviation surface sensible heat flux 239034: - std_slhtf - Time-standard-deviation surface latent heat flux 239035: - std_sdswrf - Time-standard-deviation surface downward short-wave radiation flux 239036: - std_sdlwrf - Time-standard-deviation surface downward long-wave radiation flux 239037: - std_snswrf - Time-standard-deviation surface net short-wave radiation flux 239038: - std_snlwrf - Time-standard-deviation surface net long-wave radiation flux 239039: - std_tnswrf - Time-standard-deviation top net short-wave radiation flux 239040: - std_tnlwrf - Time-standard-deviation top net long-wave radiation flux 239041: - std_iews - Time-standard-deviation eastward turbulent surface stress 239042: - std_inss - Time-standard-deviation northward turbulent surface stress 239043: - std_ie - Time-standard-deviation evaporation rate 239045: - std_iegwss - Time-standard-deviation eastward gravity wave surface stress 239046: - std_ingwss - Time-standard-deviation northward gravity wave surface stress 239047: - std_igwd - Time-standard-deviation gravity wave dissipation 239048: - std_rorwe - Time-standard-deviation runoff rate 239049: - std_tnswrfcs - Time-standard-deviation top net short-wave radiation flux, clear sky 239050: - std_tnlwrfcs - Time-standard-deviation top net long-wave radiation flux, clear sky 239051: - std_snswrfcs - Time-standard-deviation surface net short-wave radiation flux, clear sky 239052: - std_snlwrfcs - Time-standard-deviation surface net long-wave radiation flux, clear sky 239053: - std_tdswrf - Time-standard-deviation top downward short-wave radiation flux 239054: - std_vimdf - Time-standard-deviation vertically integrated moisture divergence 239055: - std_tprate - Time-standard-deviation total precipitation rate 239056: - std_csfr - Time-standard-deviation convective snowfall rate water equivalent 239057: - std_lssfr - Time-standard-deviation large scale snowfall rate water equivalent 239058: - std_sdirswrf - Time-standard-deviation surface direct short-wave radiation flux 239059: - std_sdirswrfcs - Time-standard-deviation surface direct short-wave radiation flux, clear sky 239062: - std_fco2nee - Time-standard-deviation carbon dioxide net ecosystem exchange flux 239063: - std_fco2gpp - Time-standard-deviation carbon dioxide gross primary production flux 239064: - std_fco2rec - Time-standard-deviation carbon dioxide ecosystem respiration flux 239068: - std_sdswrfcs - Time-standard-deviation surface downward short-wave radiation flux, clear sky 239069: - std_sdlwrfcs - Time-standard-deviation surface downward long-wave radiation flux, clear sky 239070: - std_pevr - Time-standard-deviation potential evaporation rate 239077: - std_vsw - Time-standard-deviation volumetric soil moisture 239078: - std_sd - Time-standard-deviation snow depth water equivalent 239079: - std_skt - Time-standard-deviation skin temperature 239080: - std_rsn - Time-standard-deviation snow density 239083: - std_ci - Time-standard-deviation sea ice area fraction 239084: - std_sst - Time-standard-deviation sea surface temperature 239085: - std_lai_lv - Time-standard-deviation leaf area index, low vegetation 239086: - std_lai_hv - Time-standard-deviation leaf area index, high vegetation 239087: - std_tclw - Time-standard-deviation total column cloud liquid water 239088: - std_tciw - Time-standard-deviation total column cloud ice water 239089: - std_2sh - Time-standard-deviation 2 metre specific humidity 239090: - std_lmlt - Time-standard-deviation lake mix-layer temperature 239091: - std_lmld - Time-standard-deviation lake mix-layer depth 239093: - std_fscov - Time-standard-deviation fraction of snow cover 239094: - std_sot - Time-standard-deviation soil temperature 239097: - std_ws - Time-standard-deviation wind speed 239098: - std_pres - Time-standard-deviation pressure 239099: - std_chnk - Time-standard-deviation charnock 239100: - std_pv - Time-standard-deviation potential vorticity 239101: - std_crwc - Time-standard-deviation specific rain water content 239102: - std_cswc - Time-standard-deviation specific snow water content 239103: - std_etadot - Time-standard-deviation eta-coordinate vertical velocity 239105: - std_vis - Time-standard-deviation visibility 239106: - std_wdir - Time-standard-deviation wind direction 239107: - std_tcsw - Time-standard-deviation total column snow water 239108: - std_lcc - Time-standard-deviation low cloud cover 239109: - std_mcc - Time-standard-deviation medium cloud cover 239110: - std_hcc - Time-standard-deviation high cloud cover 239111: - std_tcrw - Time-standard-deviation total column rain water 239117: - std_mucape - Time-standard-deviation most-unstable CAPE 239120: - std_tcolg - Time-standard-deviation total column vertically-integrated graupel (snow pellets) 239129: - std_z - Time-standard-deviation geopotential 239130: - std_t - Time-standard-deviation temperature 239131: - std_u - Time-standard-deviation u component of wind 239132: - std_v - Time-standard-deviation v component of wind 239133: - std_q - Time-standard-deviation specific humidity 239134: - std_sp - Time-standard-deviation surface pressure 239135: - std_w - Time-standard-deviation vertical velocity 239136: - std_tcw - Time-standard-deviation total column water 239137: - std_tcwv - Time-standard-deviation total column vertically-integrated water vapour 239138: - std_vo - Time-standard-deviation vorticity (relative) 239151: - std_msl - Time-standard-deviation mean sea level pressure 239152: - std_lnsp - Time-standard-deviation logarithm of surface pressure 239155: - std_d - Time-standard-deviation divergence 239157: - std_r - Time-standard-deviation relative humidity 239159: - std_blh - Time-standard-deviation boundary layer height 239165: - std_10u - Time-standard-deviation 10 metre U wind component 239166: - std_10v - Time-standard-deviation 10 metre V wind component 239167: - std_2t - Time-standard-deviation 2 metre temperature 239168: - std_2d - Time-standard-deviation 2 metre dewpoint temperature 239189: - std_suns - Time-standard-deviation sunshine 239203: - std_o3 - Time-standard-deviation ozone mass mixing ratio 239207: - std_10si - Time-standard-deviation 10 metre wind speed 239238: - std_tsn - Time-standard-deviation temperature of snow layer 239244: - std_fsr - Time-standard-deviation forecast surface roughness 239245: - std_flsr - Time-standard-deviation forecast logarithm of surface roughness for heat 239246: - std_clwc - Time-standard-deviation specific cloud liquid water content 239247: - std_ciwc - Time-standard-deviation specific cloud ice water content 239248: - std_cc - Time-standard-deviation fraction of cloud cover 239257: - std_kx - Time-standard-deviation k index 239258: - std_totalx - Time-standard-deviation total totals index 239261: - std_10wdir - Time-standard-deviation 10 metre wind direction 239262: - std_cat - Time-standard-deviation clear air turbulence (CAT) 239263: - std_al - Time-standard-deviation forecast albedo 239269: - std_pt - Time-standard-deviation potential temperature 239281: - std_aluvp_p - Time-standard-deviation UV visible albedo for direct radiation (climatological) 239282: - std_aluvd_p - Time-standard-deviation UV visible albedo for diffuse radiation (climatological) 239283: - std_alnip_p - Time-standard-deviation near IR albedo for direct radiation (climatological) 239284: - std_alnid_p - Time-standard-deviation near IR albedo for diffuse radiation (climatological) 239285: - std_asn - Time-standard-deviation snow albedo 239286: - std_mont - Time-standard-deviation montgomery potential 239287: - std_cape - Time-standard-deviation convective available potential energy 239288: - std_tcc - Time-standard-deviation total cloud cover 239289: - std_srcon - Time-standard-deviation skin reservoir content 239290: - std_tcioz - Time-standard-deviation total column integrated ozone 239291: - std_vike - Time-standard-deviation total column vertically-integrated kinetic energy 239292: - std_vithe - Time-standard-deviation total column vertically-integrated enthalpy 239293: - std_vipie - Time-standard-deviation total column vertically-integrated potential + internal energy 239294: - std_vipile - Time-standard-deviation vertical integral of potential+internal+latent energy 239295: - std_vitoe - Time-standard-deviation total column vertically-integrated total energy 239296: - std_viwe - Time-standard-deviation total column vertically-integrated water enthalpy 239297: - std_aluvpi_p - Time-standard-deviation UV visible albedo for direct radiation, isotropic component (climatological) 239298: - std_aluvpv_p - Time-standard-deviation UV visible albedo for direct radiation, volumetric component (climatological) 239299: - std_aluvpg_p - Time-standard-deviation UV visible albedo for direct radiation, geometric component (climatological) 239300: - std_alnipi_p - Time-standard-deviation near IR albedo for direct radiation, isotropic component (climatological) 239301: - std_alnipv_p - Time-standard-deviation near IR albedo for direct radiation, volumetric component (climatological) 239302: - std_alnipg_p - Time-standard-deviation near IR albedo for direct radiation, geometric component (climatological) 239303: - std_cin - Time-standard-deviation convective inhibition 239304: - std_zust - Time-standard-deviation friction velocity 239305: - std_lblt - Time-standard-deviation lake bottom temperature 239306: - std_ltlt - Time-standard-deviation lake total layer temperature 239307: - std_lshf - Time-standard-deviation lake shape factor 239308: - std_lict - Time-standard-deviation lake ice surface temperature 239309: - std_licd - Time-standard-deviation lake ice total depth 239310: - std_dndzn - Time-standard-deviation minimum vertical gradient of refractivity inside trapping layer 239311: - std_dndza - Time-standard-deviation mean vertical gradient of refractivity inside trapping layer 239312: - std_dctb - Time-standard-deviation duct base height 239313: - std_tplb - Time-standard-deviation trapping layer base height 239314: - std_tplt - Time-standard-deviation trapping layer top height 239315: - std_degm10l - Time-standard-deviation geometric height of -10 degrees C atmospheric isothermal level above ground 239316: - std_cbh - Time-standard-deviation cloud base height 239317: - std_deg0l - Time-standard-deviation geometric height of 0 degrees C atmospheric isothermal level above ground 239318: - std_i10fg - Time-standard-deviation 10 metre wind gust 239319: - std_rhw - Time-standard-deviation relative humidity with respect to water 239320: - std_2rhw - Time-standard-deviation 2 metre relative humidity with respect to water 239321: - std_capes - Time-standard-deviation convective available potential energy shear 239322: - std_trpp - Time-standard-deviation tropopause pressure 239323: - std_hcct - Time-standard-deviation height of convective cloud top 239324: - std_hwbt0 - Time-standard-deviation height of zero-degree wet-bulb temperature 239325: - std_hwbt1 - Time-standard-deviation height of one-degree wet-bulb temperature 239326: - std_litoti - Time-standard-deviation total lightning flash density 239327: - std_tcslw - Time-standard-deviation total column supercooled liquid water 239328: - std_u10n - Time-standard-deviation 10 metre U-component of neutral wind 239329: - std_v10n - Time-standard-deviation 10 metre V-component of neutral wind 239330: - std_crr - Time-standard-deviation convective rain rate 239331: - std_lsrr - Time-standard-deviation large scale rain rate 239332: - std_mlcape50 - Time-standard-deviation mixed-layer CAPE in the lowest 50 hPa 239333: - std_mlcin50 - Time-standard-deviation mixed-layer CIN in the lowest 50 hPa 239334: - std_mlcape100 - Time-standard-deviation mixed-layer CAPE in the lowest 100 hPa 239335: - std_mlcin100 - Time-standard-deviation mixed-layer CIN in the lowest 100 hPa 239336: - std_mudlp - Time-standard-deviation departure level of the most unstable parcel expressed as Pressure 239337: - std_ceil - Time-standard-deviation ceiling 239338: - std_tcsqw - Time-standard-deviation total column integrated saturation specific humidity with respect to water 239339: - std_sdirnswrf - Time-standard-deviation direct solar radiation flux 239340: - std_cossza - Time-standard-deviation cosine of solar zenith angle 239341: - std_fprate - Time-standard-deviation freezing rain rate water equivalent 239342: - std_vige - Time-standard-deviation total column vertically-integrated eastward geopotential flux 239343: - std_vign - Time-standard-deviation total column vertically-integrated northward geopotential flux 239344: - std_viwgd - Time-standard-deviation total column vertically-integrated divergence of water geopotential flux 239345: - std_vigd - Time-standard-deviation total column vertically-integrated divergence of geopotential flux 239346: - std_viee - Time-standard-deviation total column vertically-integrated eastward enthalpy flux 239347: - std_vien - Time-standard-deviation total column vertically-integrated northward enthalpy flux 239348: - std_vikee - Time-standard-deviation total column vertically-integrated eastward kinetic energy flux 239349: - std_viken - Time-standard-deviation total column vertically-integrated northward kinetic energy flux 239350: - std_vitee - Time-standard-deviation total column vertically-integrated eastward total energy flux 239351: - std_viten - Time-standard-deviation total column vertically-integrated northward total energy flux 239352: - std_vied - Time-standard-deviation total column vertically-integrated divergence of enthalpy flux 239353: - std_viked - Time-standard-deviation total column vertically-integrated divergence of kinetic energy flux 239354: - std_vited - Time-standard-deviation total column vertically-integrated divergence of total energy flux 239355: - std_viwed - Time-standard-deviation total column vertically-integrated divergence of water enthalpy flux 239356: - std_vimad - Time-standard-deviation vertically integrated divergence of mass flux 239357: - std_vimae - Time-standard-deviation vertically integrated eastward mass flux 239358: - std_viman - Time-standard-deviation vertically integrated northward mass flux 239359: - std_viwvd - Time-standard-deviation vertically integrated divergence of water vapour flux 239360: - std_viclwd - Time-standard-deviation vertically integrated divergence of cloud liquid water flux 239361: - std_viciwd - Time-standard-deviation vertically integrated divergence of cloud ice water flux 239362: - std_vird - Time-standard-deviation vertically integrated divergence of rain flux 239363: - std_visd - Time-standard-deviation vertically integrated divergence of snow flux 239364: - std_viwve - Time-standard-deviation vertically integrated eastward water vapour flux 239365: - std_viwvn - Time-standard-deviation vertically integrated northward water vapour flux 239366: - std_viclwe - Time-standard-deviation vertically integrated eastward cloud liquid water flux 239367: - std_viclwn - Time-standard-deviation vertically integrated northward cloud liquid water flux 239368: - std_viciwe - Time-standard-deviation vertically integrated eastward cloud ice water flux 239369: - std_viciwn - Time-standard-deviation vertically integrated northward cloud ice water flux 239370: - std_vire - Time-standard-deviation vertically integrated eastward rain flux 239371: - std_virn - Time-standard-deviation vertically integrated northward rain flux 239372: - std_vise - Time-standard-deviation vertically integrated eastward snow flux 239373: - std_visn - Time-standard-deviation vertically integrated northward snow flux 239374: - std_vioze - Time-standard-deviation vertically integrated eastward ozone flux 239375: - std_viozn - Time-standard-deviation vertically integrated northward ozone flux 239376: - std_viozd - Time-standard-deviation vertically integrated divergence of ozone flux 239377: - std_vions - Time-standard-deviation vertically integrated net source of ozone 239378: - std_ietssofd - Time-standard-deviation eastward turbulent surface stress due to orographic form drag 239379: - std_intssofd - Time-standard-deviation northward turbulent surface stress due to orographic form drag 239380: - std_ietsssr - Time-standard-deviation eastward turbulent surface stress due to surface roughness 239381: - std_intsssr - Time-standard-deviation northward turbulent surface stress due to surface roughness 239383: - std_licgi - Time-standard-deviation cloud-to-ground lightning flash density 239386: - std_lshnf - Time-standard-deviation land surface heat net flux 239387: - std_sdirnswrfcs - Time-standard-deviation surface direct normal short-wave radiation flux, clear sky 239388: - std_10cogu - Time-standard-deviation 10 metre convective gust 239389: - std_10tugu - Time-standard-deviation 10 metre turbulent gust 239390: - std_h0thg - Time-standard-deviation geometric height of 0 degrees C theta level above ground 239391: - std_h1thg - Time-standard-deviation geometric height of 1 degree C theta level above ground 239392: - std_h1p5thg - Time-standard-deviation geometric height of 1.5 degrees C theta level above ground 239393: - std_veg - Time-standard-deviation vegetation 239394: - std_lai - Time-standard-deviation leaf area index 239395: - std_srhe - Time-standard-deviation surface roughness for heat 239396: - std_rol - Time-standard-deviation Reciprocal Obukhov length 239397: - std_deg3l - Time-standard-deviation geometric height of 3 degrees C atmospheric isothermal level above ground 239404: - std_sdifswrfcs - Time-standard-deviation surface diffuse short-wave radiation flux, clear sky 239405: - std_vswrz - Time-standard-deviation volumetric soil moisture (root zone) 239406: - std_lwcs - Time-standard-deviation liquid water content in snow pack 239407: - std_mucin - Time-standard-deviation most-unstable CIN 239408: - std_crwc_conv - Time-standard-deviation specific rain water content (convective) 239409: - std_cswc_conv - Time-standard-deviation specific snow water content (convective) 239410: - std_mld - Time-standard-deviation mixed layer depth 239411: - std_cur - Time-standard-deviation urban cover 240011: - chcross - Cross sectional area of flow in channel 240012: - chside - Side flow into river channel 240013: - dis - Discharge from rivers or streams 240014: - rivsto - River storage of water 240015: - fldsto - Floodplain storage of water 240016: - fldfrc - Water fraction 240017: - dslr - Days since last observation 240018: - frost - Frost index 240020: - woss - Depth of water on soil surface 240021: - tpups - Upstream accumulated precipitation 240022: - smups - Upstream accumulated snow melt 240023: - dis06 - Mean discharge in the last 6 hours 240024: - dis24 - Mean discharge in the last 24 hours 240026: - sd_elev - Snow depth at elevation bands 240028: - gwus - Groundwater upper storage 240029: - gwls - Groundwater lower storage 240030: - lakdph - Lake depth 240031: - rivdph - River depth 240032: - rivout - River outflow of water 240033: - fldout - Floodplain outflow of water 240034: - pthflw - Floodpath outflow of water 240035: - flddep - Floodplain depth 240036: - fldffr - Floodplain flooded fraction 240037: - fldfar - Floodplain flooded area 240038: - rivfr - River fraction 240039: - rivar - River area 240040: - rivcffr - Fraction of river coverage plus river related flooding 240041: - rivcfar - Area of river coverage plus river related flooding 250001: - lat - Latitude 250002: - lon - Longitude 250003: - tlat - Latitude on T grid 250004: - tlon - Longitude on T grid 250005: - ulat - Latitude on U grid 250006: - ulon - Longitude on U grid 250007: - vlat - Latitude on V grid 250008: - vlon - Longitude on V grid 250009: - wlat - Latitude on W grid 250010: - wlon - Longitude on W grid 250011: - flat - Latitude on F grid 250012: - flon - Longitude on F grid 254001: - covar_t2m_swvl1 - Covariance between 2-metre temperature and volumetric soil water layer 1 254002: - covar_rh2m_swvl1 - Covariance between 2-metre relative humidity and volumetric soil water layer 1 254003: - covar_ssm_swvl1 - Covariance between surface soil moisture and volumetric soil water layer 1 254004: - covar_t2m_swvl2 - Covariance between 2-metre temperature and volumetric soil water layer 2 254005: - covar_rh2m_swvl2 - Covariance between 2-metre relative humidity and volumetric soil water layer 2 254006: - covar_ssm_swvl2 - Covariance between surface soil moisture and volumetric soil water layer 2 254007: - covar_t2m_swvl3 - Covariance between 2-metre temperature and volumetric soil water layer 3 254008: - covar_rh2m_swvl3 - Covariance between 2-metre relative humidity and volumetric soil water layer 3 254009: - covar_ssm_swvl3 - Covariance between surface soil moisture and volumetric soil water layer 3 254010: - covar_t2m_stl1 - Covariance between 2-metre temperature and soil temperature layer 1 254011: - covar_rh2m_stl1 - Covariance between 2-metre relative humidity and soil temperature layer 1 254012: - covar_t2m_stl2 - Covariance between 2-metre temperature and soil temperature layer 2 254013: - covar_rh2m_stl2 - Covariance between 2-metre relative humidity and soil temperature layer 2 254014: - covar_t2m_stl3 - Covariance between 2-metre temperature and soil temperature layer 3 254015: - covar_rh2m_stl3 - Covariance between 2-metre relative humidity and soil temperature layer 3 254016: - covar_t2m_tsn1 - Covariance between 2-metre temperature and temperature of snow layer 1 254017: - covar_rh2m_tsn1 - Covariance between 2-metre relative humidity and temperature of snow layer 1 254018: - covar_t2m_tsn2 - Covariance between 2-metre temperature and temperature of snow layer 2 254019: - covar_rh2m_tsn2 - Covariance between 2-metre relative humidity and temperature of snow layer 2 254020: - covar_t2m_tsn3 - Covariance between 2-metre temperature and temperature of snow layer 3 254021: - covar_rh2m_tsn3 - Covariance between 2-metre relative humidity and temperature of snow layer 3 260001: - tcolg - Total column vertically-integrated graupel (snow pellets) 260002: - slhtf - Surface latent heat net flux 260004: - heatx - Heat index 260005: - wcf - Wind chill factor 260006: - mindpd - Minimum dew point depression 260007: - snohf - Snow phase change heat flux 260008: - vapp - Vapor pressure 260009: - ncpcp - Large scale precipitation (non-convective) 260010: - srweq - Snowfall rate water equivalent 260011: - snoc - Convective snow 260012: - snol - Large scale snow 260013: - snoag - Snow age 260014: - absh - Absolute humidity 260015: - ptype - Precipitation type 260016: - iliqw - Integrated liquid water 260017: - tcond - Condensate 260018: - clwmr - Cloud mixing ratio 260019: - icmr - Ice water mixing ratio 260020: - rwmr - Rain mixing ratio 260021: - snmr - Snow mixing ratio 260022: - mconv - Horizontal moisture convergence 260023: - maxrh - Maximum relative humidity 260024: - maxah - Maximum absolute humidity 260025: - asnow - Total snowfall 260026: - pwcat - Precipitable water category 260027: - hail 260028: - grle - Graupel (snow pellets) 260029: - crain - Categorical rain 260030: - cfrzr - Categorical freezing rain 260031: - cicep - Categorical ice pellets 260032: - csnow - Categorical snow 260033: - cpr - Convective precipitation rate 260034: - mdiv - Horizontal moisture divergence 260035: - cpofp - Percent frozen precipitation 260036: - pevap - Potential evaporation 260038: - snowc - Snow cover 260039: - frain - Rain fraction of total cloud water 260040: - rime - Rime factor 260041: - tcolr - Total column integrated rain 260042: - tcols - Total column integrated snow 260043: - lswp - Large scale water precipitation (non-convective) 260044: - cwp - Convective water precipitation 260045: - twatp - Total water precipitation 260046: - tsnowp - Total snow precipitation 260047: - tcwat - Total column water (Vertically integrated total water (vapour + cloud water/ice)) 260048: - tprate - Total precipitation rate 260049: - tsrwe - Total snowfall rate water equivalent 260050: - lsprate - Large scale precipitation rate 260053: - tsrate - Total snowfall rate 260054: - csrate - Convective snowfall rate 260055: - lssrate - Large scale snowfall rate 260056: - sdwe - Water equivalent of accumulated snow depth (deprecated) 260057: - tciwv - Total column integrated water vapour 260058: - rprate - Rain precipitation rate 260059: - sprate - Snow precipitation rate 260060: - fprate - Freezing rain precipitation rate 260061: - iprate - Ice pellets precipitation rate 260062: - uflx - Momentum flux, u component 260063: - vflx - Momentum flux, v component 260064: - maxgust - Maximum wind speed 260065: - gust - Wind speed (gust) 260066: - ugust - u-component of wind (gust) 260067: - vgust - v-component of wind (gust) 260068: - vwsh - Vertical speed shear 260069: - mflx - Horizontal momentum flux 260070: - ustm - U-component storm motion 260071: - vstm - V-component storm motion 260072: - cd - Drag coefficient 260073: - fricv - Frictional velocity 260074: - prmsl - Pressure reduced to MSL 260076: - alts - Altimeter setting 260077: - thick - Thickness 260078: - presalt - Pressure altitude 260079: - denalt - Density altitude 260080: - 5wavh - 5-wave geopotential height 260081: - iegwss - Instantaneous eastward gravity wave surface stress 260082: - ingwss - Instantaneous northward gravity wave surface stress 260084: - 5wava - 5-wave geopotential height anomaly 260085: - sdsgso - Standard deviation of sub-grid scale orography 260086: - nswrt - Net short-wave radiation flux (top of atmosphere) 260087: - sdswrf - Surface downward short-wave radiation flux 260088: - suswrf - Surface upward short-wave radiation flux 260089: - snswrf - Surface net short-wave radiation flux 260090: - sparf - Surface photosynthetically active radiation flux 260091: - snswrfcs - Surface net short-wave radiation flux, clear sky 260092: - sduvrf - Surface downward UV radiation flux 260093: - uviucs - UV index (under clear sky) 260094: - uvi - UV index 260095: - nlwrs - Net long wave radiation flux (surface) 260096: - nlwrt - Net long wave radiation flux (top of atmosphere) 260097: - sdlwrf - Surface downward long-wave radiation flux 260098: - sulwrf - Surface upward long-wave radiation flux 260099: - snlwrf - Surface net long-wave radiation flux 260100: - snlwrfcs - Surface net long-wave radiation flux, clear sky 260101: - cice - Cloud Ice 260102: - cwat - Cloud water 260103: - cdca - Cloud amount 260104: - cdct - Cloud type 260105: - tmaxt - Thunderstorm maximum tops 260106: - thunc - Thunderstorm coverage 260107: - cdcb - Cloud base 260108: - cdct - Cloud top 260109: - ceil - Ceiling 260110: - cdlyr - Non-convective cloud cover 260111: - cwork - Cloud work function 260112: - cuefi - Convective cloud efficiency 260113: - tcond - Total condensate 260114: - tcolw - Total column-integrated cloud water 260115: - tcoli - Total column-integrated cloud ice 260116: - tcolc - Total column-integrated condensate 260117: - fice - Ice fraction of total condensate 260118: - cdcimr - Cloud ice mixing ratio 260119: - suns - Sunshine 260120: - _param_260120 - Horizontal extent of cumulonimbus (CB) 260121: - kx - K index 260122: - kox - KO index 260123: - totalx - Total totals index 260124: - sx - Sweat index 260125: - hlcy - Storm relative helicity 260126: - ehlx - Energy helicity index 260127: - lftx - Surface lifted index 260128: - 4lftx - Best (4-layer) lifted index 260129: - aerot - Aerosol type 260130: - tozne - Total ozone 260131: - o3mr - Ozone mixing ratio 260132: - tcioz - Total column integrated ozone 260133: - bswid - Base spectrum width 260134: - bref - Base reflectivity 260135: - brvel - Base radial velocity 260136: - veril - Vertically-integrated liquid 260137: - lmaxbr - Layer-maximum base reflectivity 260138: - rdp - Precipitation from radar 260139: - acces - Air concentration of Caesium 137 260140: - aciod - Air concentration of Iodine 131 260141: - acradp - Air concentration of radioactive pollutant 260142: - gdces - Ground deposition of Caesium 137 260143: - gdiod - Ground deposition of Iodine 131 260144: - gdradp - Ground deposition of radioactive pollutant 260145: - tiaccp - Time-integrated air concentration of caesium pollutant 260146: - tiacip - Time-integrated air concentration of iodine pollutant 260147: - tiacrp - Time-integrated air concentration of radioactive pollutant 260148: - volash - Volcanic ash 260149: - icit - Icing top 260150: - icib - Icing base 260151: - ici - Icing 260152: - turbt - Turbulence top 260153: - turbb - Turbulence base 260154: - turb - Turbulence 260155: - tke - Turbulent kinetic energy 260156: - pblreg - Planetary boundary layer regime 260157: - conti - Contrail intensity 260158: - contet - Contrail engine type 260159: - contt - Contrail top 260160: - contb - Contrail base 260161: - mxsalb - Maximum snow albedo 260162: - snfalb - Snow free albedo 260163: - _param_260163 - Icing 260164: - _param_260164 - In-cloud turbulence 260165: - rcat - Relative clear air turbulence (RCAT) 260166: - sldp - Supercooled large droplet probability 260167: - var190m0 - Arbitrary text string 260168: - tsec - Seconds prior to initial reference time (defined in Section 1) 260169: - ffldg - Flash flood guidance 260170: - ffldro - Flash flood runoff (Encoded as an accumulation over a floating subinterval of time) 260171: - rssc - Remotely sensed snow cover 260172: - esct - Elevation of snow covered terrain 260173: - swepon - Snow water equivalent percent of normal 260174: - bgrun - Baseflow-groundwater runoff 260175: - ssrun - Storm surface runoff 260176: - cppop - Conditional percent precipitation amount fractile for an overall period (Encoded as an accumulation) 260177: - pposp - Percent precipitation in a sub-period of an overall period 260178: - pop - Probability of 0.01 inch of precipitation (POP) 260180: - veg - Vegetation 260181: - watr - Water runoff 260182: - evapt - Evapotranspiration 260183: - mterh - Model terrain height 260184: - landu - Land use 260185: - soilw - Volumetric soil moisture content 260186: - gflux - Ground heat flux 260187: - mstav - Moisture availability 260188: - sfexc - Exchange coefficient 260189: - cnwat - Plant canopy surface water 260190: - bmixl - Blackadar mixing length scale 260191: - ccond - Canopy conductance 260192: - rsmin - Minimal stomatal resistance 260193: - rcs - Solar parameter in canopy conductance 260194: - rct - Temperature parameter in canopy conductance 260195: - rcsol - Soil moisture parameter in canopy conductance 260196: - rcq - Humidity parameter in canopy conductance 260197: - cisoilw - Column-integrated soil water 260198: - hflux - Heat flux 260199: - vsw - Volumetric soil moisture 260200: - vwiltm - Volumetric wilting point 260201: - uplst - Upper layer soil temperature 260202: - uplsm - Upper layer soil moisture 260203: - lowlsm - Lower layer soil moisture 260204: - botlst - Bottom layer soil temperature 260205: - soill - Liquid volumetric soil moisture (non-frozen) 260206: - rlyrs - Number of soil layers in root zone 260207: - smref - Transpiration stress-onset (soil moisture) 260208: - smdry - Direct evaporation cease (soil moisture) 260209: - poros - Soil porosity 260210: - liqvsm - Liquid volumetric soil moisture (non-frozen) 260211: - voltso - Volumetric transpiration stress-onset (soil moisture) 260212: - transo - Transpiration stress-onset (soil moisture) 260213: - voldec - Volumetric direct evaporation cease (soil moisture) 260214: - direc - Direct evaporation cease (soil moisture) 260215: - soilp - Soil porosity 260216: - vsosm - Volumetric saturation of soil moisture 260217: - satosm - Saturation of soil moisture 260218: - estp - Estimated precipitation 260219: - irrate - Instantaneous rain rate 260220: - ctoph - Cloud top height 260221: - ctophqi - Cloud top height quality indicator 260222: - estu - Estimated u component of wind 260223: - estv - Estimated v component of wind 260224: - npixu - Number of pixels used 260225: - solza - Solar zenith angle 260226: - raza - Relative azimuth angle 260227: - rfl06 - Reflectance in 0.6 micron channel 260228: - rfl08 - Reflectance in 0.8 micron channel 260229: - rfl16 - Reflectance in 1.6 micron channel 260230: - rfl39 - Reflectance in 3.9 micron channel 260231: - atmdiv - Atmospheric divergence 260232: - wvdir - Direction of wind waves 260233: - dirpw - Primary wave direction 260234: - perpw - Primary wave mean period 260235: - persw - Secondary wave mean period 260236: - dirc - Current direction 260237: - spc - Current speed 260238: - wz - Geometric vertical velocity 260241: - tsec - Seconds prior to initial reference time (defined in Section 1) 260242: - 2r - 2 metre relative humidity 260243: - ttrad - Temperature tendency by all radiation 260244: - rev - Relative Error Variance 260245: - lrghr - Large Scale Condensate Heating rate 260246: - cnvhr - Deep Convective Heating rate 260247: - thflx - Total Downward Heat Flux at Surface 260248: - ttdia - Temperature Tendency By All Physics 260249: - ttphy - Temperature Tendency By Non-radiation Physics 260250: - tsd1d - Standard Dev. of IR Temp. over 1x1 deg. area 260251: - shahr - Shallow Convective Heating rate 260252: - vdfhr - Vertical Diffusion Heating rate 260253: - thz0 - Potential temperature at top of viscous sublayer 260254: - tchp - Tropical Cyclone Heat Potential 260255: - aptmp - Apparent temperature 260256: - hindex - Haines Index 260257: - ccl - Cloud cover 260259: - eva - Evaporation 260260: - 10wdir - 10 metre wind direction 260261: - minrh - Minimum Relative Humidity 260262: - sdirswrf - Surface direct short-wave radiation flux 260263: - sdifswrf - Surface diffuse short-wave radiation flux 260264: - tidirswrf - Time-integrated surface direct short wave radiation flux 260265: - eva06 - Evaporation in the last 6 hours 260266: - eva24 - Evaporation in the last 24 hours 260267: - tp06 - Total precipitation in the last 6 hours 260268: - tp24 - Total precipitation in the last 24 hours 260269: - tipd - Total Icing Potential Diagnostic 260270: - ncip - Number concentration for ice particles 260271: - snot - Snow temperature 260272: - tclsw - Total column-integrated supercooled liquid water 260273: - tcolm - Total column-integrated melting ice 260274: - emnp - Evaporation - Precipitation 260275: - sbsno - Sublimation (evaporation from snow) 260276: - cnvmr - Deep Convective Moistening Rate 260277: - shamr - Shallow Convective Moistening Rate 260278: - vdfmr - Vertical Diffusion Moistening Rate 260279: - condp - Condensation Pressure of Parcali Lifted From Indicate Surface 260280: - lrgmr - Large scale moistening rate 260281: - qz0 - Specific humidity at top of viscous sublayer 260282: - qmax - Maximum specific humidity at 2m 260283: - qmin - Minimum specific humidity at 2m 260284: - arain - Liquid precipitation (rainfall) 260285: - snowt - Snow temperature, depth-avg 260286: - apcpn - Total precipitation (nearest grid point) 260287: - acpcpn - Convective precipitation (nearest grid point) 260288: - frzr - Freezing Rain 260289: - fscov - Fraction of snow cover 260290: - cat - Clear air turbulence (CAT) 260291: - mwt - Mountain wave turbulence (eddy dissipation rate) 260292: - crwc_conv - Specific rain water content (convective) 260293: - cswc_conv - Specific snow water content (convective) 260294: - glm - Glacier mask 260295: - lauv - Latitude of U Wind Component of Velocity 260296: - louv - Longitude of U Wind Component of Velocity 260297: - lavv - Latitude of V Wind Component of Velocity 260298: - lovv - Longitude of V Wind Component of Velocity 260299: - lapp - Latitude of Pressure Point 260300: - lopp - Longitude of Pressure Point 260301: - vedh - Vertical Eddy Diffusivity Heat exchange 260302: - covmz - Covariance between Meridional and Zonal Components of the wind. 260303: - covtz - Covariance between Temperature and Zonal Components of the wind. 260304: - covtm - Covariance between Temperature and Meridional Components of the wind. 260305: - vdfua - Vertical Diffusion Zonal Acceleration 260306: - vdfva - Vertical Diffusion Meridional Acceleration 260307: - gwdu - Gravity wave drag zonal acceleration 260308: - gwdv - Gravity wave drag meridional acceleration 260309: - cnvu - Convective zonal momentum mixing acceleration 260310: - cnvv - Convective meridional momentum mixing acceleration 260311: - wtend - Tendency of vertical velocity 260312: - omgalf - Omega (Dp/Dt) divide by density 260313: - cngwdu - Convective Gravity wave drag zonal acceleration 260314: - cngwdv - Convective Gravity wave drag meridional acceleration 260315: - lmv - Velocity Point Model Surface 260316: - pvmww - Potential Vorticity (Mass-Weighted) 260317: - mslet - MSLP (Eta model reduction) 260318: - ptype_sev1h - Precipitation type (most severe) in the last 1 hour 260319: - ptype_sev3h - Precipitation type (most severe) in the last 3 hours 260320: - ptype_freq1h - Precipitation type (most frequent) in the last 1 hour 260321: - ptype_freq3h - Precipitation type (most frequent) in the last 3 hours 260323: - mslma - MSLP (MAPS System Reduction) 260324: - tslsa - 3-hr pressure tendency (Std. Atmos. Reduction) 260325: - plpl - Pressure of level from which parcel was lifted 260326: - lpsx - X-gradient of Log Pressure 260327: - lpsy - Y-gradient of Log Pressure 260328: - hgtx - X-gradient of Height 260329: - hgty - Y-gradient of Height 260330: - layth - Layer Thickness 260331: - nlgsp - Natural Log of Surface Pressure 260332: - cnvumf - Convective updraft mass flux 260333: - cnvdmf - Convective downdraft mass flux 260334: - cnvdemf - Convective detrainment mass flux 260335: - lmh - Mass Point Model Surface 260336: - hgtn - Geopotential Height (nearest grid point) 260337: - presn - Pressure (nearest grid point) 260338: - ptype_sev6h - Precipitation type (most severe) in the last 6 hours 260339: - ptype_freq6h - Precipitation type (most frequent) in the last 6 hours 260340: - duvb - UV-B downward solar flux 260341: - cduvb - Clear sky UV-B downward solar flux 260342: - csdsf - Clear Sky Downward Solar Flux 260343: - swhr - Solar Radiative Heating Rate 260344: - csusf - Clear Sky Upward Solar Flux 260345: - cfnsf - Cloud Forcing Net Solar Flux 260346: - vbdsf - Visible Beam Downward Solar Flux 260347: - vddsf - Visible Diffuse Downward Solar Flux 260348: - nbdsf - Near IR Beam Downward Solar Flux 260349: - nddsf - Near IR Diffuse Downward Solar Flux 260350: - dtrf - Downward Total radiation Flux 260351: - utrf - Upward Total radiation Flux 260354: - lwhr - Long-Wave Radiative Heating Rate 260355: - csulf - Clear Sky Upward Long Wave Flux 260356: - csdlf - Clear Sky Downward Long Wave Flux 260357: - cfnlf - Cloud Forcing Net Long Wave Flux 260360: - sot - Soil temperature 260361: - sdswrfcs - Surface downward short-wave radiation flux, clear sky 260362: - suswrfcs - Surface upward short-wave radiation flux, clear sky 260363: - sdlwrfcs - Surface downward long-wave radiation flux, clear sky 260364: - sohf - Soil heat flux 260365: - percr - Percolation rate 260366: - mflux - Convective Cloud Mass Flux 260367: - sod - Soil depth 260368: - som - Soil moisture 260369: - ri - Richardson Number 260370: - cwdi - Convective Weather Detection Index 260372: - uphl - Updraft Helicity 260373: - lai - Leaf Area Index 260374: - pmtc - Particulate matter (coarse) 260375: - pmtf - Particulate matter (fine) 260376: - lpmtf - Particulate matter (fine) 260377: - lipmf - Integrated column particulate matter (fine) 260379: - ozcon - Ozone Concentration (PPB) 260380: - ozcat - Categorical Ozone Concentration 260381: - vdfoz - Ozone vertical diffusion 260382: - poz - Ozone production 260383: - toz - Ozone tendency 260384: - pozt - Ozone production from temperature term 260385: - pozo - Ozone production from col ozone term 260386: - refzr - Derived radar reflectivity backscatter from rain 260387: - refzi - Derived radar reflectivity backscatter from ice 260388: - refzc - Derived radar reflectivity backscatter from parameterized convection 260389: - refd - Derived radar reflectivity 260390: - refc - Maximum/Composite radar reflectivity 260391: - ltng - Lightning 260394: - srcono - Slight risk convective outlook 260395: - mrcono - Moderate risk convective outlook 260396: - hrcono - High risk convective outlook 260397: - torprob - Tornado probability 260398: - hailprob - Hail probability 260399: - windprob - Wind probability 260400: - storprob - Significant Tornado probability 260401: - shailpro - Significant Hail probability 260402: - swindpro - Significant Wind probability 260403: - tstmc - Categorical Thunderstorm (1-yes, 0-no) 260404: - mixly - Number of mixed layers next to surface 260405: - flght - Flight Category 260406: - cicel - Confidence - Ceiling 260407: - civis - Confidence - Visibility 260408: - ciflt - Confidence - Flight Category 260409: - lavni - Low-Level aviation interest 260410: - havni - High-Level aviation interest 260411: - sbsalb - Visible, Black Sky Albedo 260412: - swsalb - Visible, White Sky Albedo 260413: - nbsalb - Near IR, Black Sky Albedo 260414: - nwsalb - Near IR, White Sky Albedo 260415: - prsvr - Total Probability of Severe Thunderstorms (Days 2,3) 260416: - prsigsvr - Total Probability of Extreme Severe Thunderstorms (Days 2,3) 260417: - sipd - Supercooled Large Droplet (SLD) Potential 260418: - epsr - Radiative emissivity 260419: - tpfi - Turbulence Potential Forecast Index 260420: - vaftd - Volcanic Ash Forecast Transport and Dispersion 260421: - nlat - Latitude (-90 to +90) 260422: - elon - East Longitude (0 - 360) 260423: - adswrf_cs - Accumulated surface downward short-wave radiation flux, clear sky 260424: - mlyno - Model Layer number (From bottom up) 260425: - nlatn - Latitude (nearest neighbor) (-90 to +90) 260426: - elonn - East Longitude (nearest neighbor) (0 - 360) 260427: - auswrf_cs - Accumulated surface upward short-wave radiation flux, clear sky 260428: - adlwrf_cs - Accumulated surface downward long-wave radiation flux, clear sky 260429: - cpozp - Probability of Freezing Precipitation 260430: - perc - Percolation 260431: - ppffg - Probability of precipitation exceeding flash flood guidance values 260432: - cwr - Probability of Wetting Rain, exceeding in 0.10 in a given time period 260433: - etr - Evapotranspiration rate 260434: - acc_et24 - Time-integrated evapotranspiration rate in the last 24h 260435: - avg_et24 - Time-mean evapotranspiration rate in the last 24h 260436: - petr - Potential evapotranspiration rate 260437: - acc_pet24 - Time-integrated potential evapotranspiration rate in the last 24h 260438: - avg_pet24 - Time-mean potential evapotranspiration rate in the last 24h 260439: - vgtyp - Vegetation Type 260440: - avg_swv24 - Time-mean volumetric soil moisture 260441: - avg_tp24 - Time-mean total precipitation rate 260442: - wilt - Wilting Point 260443: - rorwe - Runoff rate water equivalent (surface plus subsurface) 260444: - acc_rod24 - Time-integrated water runoff and drainage rate in the last 24h 260445: - avg_rod24 - Time-mean water runoff and drainage rate in the last 24h 260447: - rdrip - Rate of water dropping from canopy to ground 260448: - icwat - Ice-free water surface 260449: - akhs - Surface exchange coefficients for T and Q divided by delta z 260450: - akms - Surface exchange coefficients for U and V divided by delta z 260451: - vegt - Vegetation canopy temperature 260452: - sstor - Surface water storage 260453: - lsoil - Liquid soil moisture content (non-frozen) 260454: - ewatr - Open water evaporation (standing water) 260455: - gwrec - Groundwater recharge 260456: - qrec - Flood plain recharge 260457: - sfcrh - Roughness length for heat 260458: - ndvi - Normalized Difference Vegetation Index 260459: - landn - Land-sea coverage (nearest neighbor) [land=1,sea=0] 260460: - amixl - Asymptotic mixing length scale 260461: - wvinc - Water vapor added by precip assimilation 260462: - wcinc - Water condensate added by precip assimilation 260463: - wvconv - Water Vapor Flux Convergence (Vertical Int) 260464: - wcconv - Water Condensate Flux Convergence (Vertical Int) 260465: - wvuflx - Water Vapor Zonal Flux (Vertical Int) 260466: - wvvflx - Water Vapor Meridional Flux (Vertical Int) 260467: - wcuflx - Water Condensate Zonal Flux (Vertical Int) 260468: - wcvflx - Water Condensate Meridional Flux (Vertical Int) 260469: - acond - Aerodynamic conductance 260470: - evcw - Canopy water evaporation 260471: - trans - Transpiration 260472: - avg_sd24 - Time-mean snow depth water equivalent 260473: - avg_skt24 - Time-mean skin temperature 260474: - sltyp - Surface Slope Type 260475: - smr - Snow melt rate 260476: - acc_smr24 - Time-integrated snow melt rate in the last 24h 260477: - avg_smr24 - Time-mean snow melt rate in the last 24h 260478: - evbs - Direct evaporation from bare soil 260479: - lspa - Land Surface Precipitation Accumulation 260480: - baret - Bare soil surface skin temperature 260481: - avsft - Average surface skin temperature 260482: - radt - Effective radiative skin temperature 260483: - fldcp - Field Capacity 260484: - usct - Scatterometer Estimated U Wind Component 260485: - vsct - Scatterometer Estimated V Wind Component 260486: - wstp - Wave Steepness 260487: - omlu - Ocean Mixed Layer U Velocity 260488: - omlv - Ocean Mixed Layer V Velocity 260489: - ubaro - Barotropic U velocity 260490: - vbaro - Barotropic V velocity 260491: - surge - Storm Surge 260492: - etsrg - Extra Tropical Storm Surge 260493: - elevhtml - Ocean Surface Elevation Relative to Geoid 260494: - sshg - Sea Surface Height Relative to Geoid 260495: - p2omlt - Ocean Mixed Layer Potential Density (Reference 2000m)
#include #include "netcdf.h" /* This is the name of the data file we will create. */ #define FILE_NAME "sfc_pres_temp.nc" /* We are writing 2D data, a 6 x 12 lat-lon grid. We will need two * netCDF dimensions. */ #define NDIMS 2 #define NLAT 6 #define NLON 12 #define LAT_NAME "latitude" #define LON_NAME "longitude" /* Names of things. */ #define PRES_NAME "pressure" #define TEMP_NAME "temperature" #define UNITS "units" #define DEGREES_EAST "degrees_east" #define DEGREES_NORTH "degrees_north" /* These are used to construct some example data. */ #define SAMPLE_PRESSURE 900 #define SAMPLE_TEMP 9.0 #define START_LAT 25.0 #define START_LON -125.0 /* Handle errors by printing an error message and exiting with a * non-zero status. */ #define ERR(e) \ { \ printf("Error: %s\n", nc_strerror(e)); \ return 2; \ } int main() { int ncid, lon_dimid, lat_dimid, pres_varid, temp_varid; /* In addition to the latitude and longitude dimensions, we will also create latitude and longitude netCDF variables which will hold the actual latitudes and longitudes. Since they hold data about the coordinate system, the netCDF term for these is: "coordinate variables." */ int lat_varid, lon_varid; int dimids[NDIMS]; /* We will write surface temperature and pressure fields. */ float pres_out[NLAT][NLON]; float temp_out[NLAT][NLON]; float lats[NLAT], lons[NLON]; /* It's good practice for each netCDF variable to carry a "units" attribute. */ char pres_units[] = "hPa"; char temp_units[] = "celsius"; /* Error handling. */ int retval; for (int lat = 0; lat < NLAT; lat++) lats[lat] = START_LAT + 5. * lat; for (int lon = 0; lon < NLON; lon++) lons[lon] = START_LON + 5. * lon; for (int lat = 0; lat < NLAT; lat++) { for (int lon = 0; lon < NLON; lon++) { pres_out[lat][lon] = SAMPLE_PRESSURE + (lon * NLAT + lat); temp_out[lat][lon] = SAMPLE_TEMP + .25 * (lon * NLAT + lat); } } /* Create the file. */ if ((retval = nc_create(FILE_NAME, NC_CLOBBER, &ncid))) ERR(retval); /* Define the dimensions. */ if ((retval = nc_def_dim(ncid, LAT_NAME, NLAT, &lat_dimid))) ERR(retval); if ((retval = nc_def_dim(ncid, LON_NAME, NLON, &lon_dimid))) ERR(retval); // define latitudes if ((retval = nc_def_var(ncid, "lat", NC_FLOAT, 1, &lat_dimid, &lat_varid))) ERR(retval); if ((retval = nc_put_att_text(ncid, lat_varid, "standard_name", strlen(LAT_NAME), LAT_NAME))) ERR(retval); if ((retval = nc_put_att_text(ncid, lat_varid, UNITS, strlen(DEGREES_NORTH), DEGREES_NORTH))) ERR(retval); // define longitudes if ((retval = nc_def_var(ncid, "lon", NC_FLOAT, 1, &lon_dimid, &lon_varid))) ERR(retval); if ((retval = nc_put_att_text(ncid, lon_varid, "standard_name", strlen(LON_NAME), LON_NAME))) ERR(retval); if ((retval = nc_put_att_text(ncid, lon_varid, UNITS, strlen(DEGREES_EAST), DEGREES_EAST))) ERR(retval); /* Define the netCDF variables. The dimids array is used to pass the dimids of the dimensions of the variables.*/ dimids[0] = lat_dimid; dimids[1] = lon_dimid; /// pressure if ((retval = nc_def_var(ncid, "press", NC_FLOAT, NDIMS, dimids, &pres_varid))) ERR(retval); if ((retval = nc_put_att_text(ncid, pres_varid, "standard_name", strlen(PRES_NAME), PRES_NAME))) ERR(retval); if ((retval = nc_put_att_text(ncid, pres_varid, UNITS, strlen(pres_units), pres_units))) ERR(retval); /// temperature if ((retval = nc_def_var(ncid, "temp", NC_FLOAT, NDIMS, dimids, &temp_varid))) ERR(retval); if ((retval = nc_put_att_text(ncid, temp_varid, "standard_name", strlen(TEMP_NAME), TEMP_NAME))) ERR(retval); if ((retval = nc_put_att_text(ncid, temp_varid, UNITS, strlen(temp_units), temp_units))) ERR(retval); /* End define mode. */ if ((retval = nc_enddef(ncid))) ERR(retval); // write data if ((retval = nc_put_var_float(ncid, lat_varid, &lats[0]))) ERR(retval); if ((retval = nc_put_var_float(ncid, lon_varid, &lons[0]))) ERR(retval); if ((retval = nc_put_var_float(ncid, pres_varid, &pres_out[0][0]))) ERR(retval); if ((retval = nc_put_var_float(ncid, temp_varid, &temp_out[0][0]))) ERR(retval); // Close the file if ((retval = nc_close(ncid))) ERR(retval); return 0; } metkit-1.16.0/src/metkit/000077500000000000000000000000001513171467200151675ustar00rootroot00000000000000metkit-1.16.0/src/metkit/CMakeLists.txt000066400000000000000000000117711513171467200177360ustar00rootroot00000000000000### config headers ecbuild_generate_config_headers( DESTINATION ${INSTALL_INCLUDE_DIR}/metkit ) configure_file( metkit_config.h.in metkit_config.h ) configure_file( metkit_version.h.in metkit_version.h ) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/metkit_config.h ${CMAKE_CURRENT_BINARY_DIR}/metkit_version.h DESTINATION ${INSTALL_INCLUDE_DIR}/metkit ) ### metkit sources list( APPEND metkit_srcs metkit_version.c config/LibMetkit.cc config/LibMetkit.h mars/BaseProtocol.cc mars/BaseProtocol.h mars/ClientTask.cc mars/ClientTask.h mars/DHSProtocol.cc mars/DHSProtocol.h mars/Matcher.cc mars/Matcher.h mars/MarsExpandContext.h mars/MarsExpansion.cc mars/MarsExpansion.h mars/MarsExpension.h mars/MarsHandle.cc mars/MarsHandle.h mars/MarsLanguage.cc mars/MarsLanguage.h mars/MarsLocation.cc mars/MarsLocation.h mars/MarsParsedRequest.cc mars/MarsParsedRequest.h mars/MarsParser.cc mars/MarsParser.h mars/MarsRequest.cc mars/MarsRequest.h mars/MarsRequestHandle.cc mars/MarsRequestHandle.h mars/Parameter.cc mars/Parameter.h mars/ParamID.cc mars/ParamID.h mars/Quantile.cc mars/Quantile.h mars/RequestEnvironment.cc mars/RequestEnvironment.h mars/StepRangeNormalise.h mars/Type.cc mars/Type.h mars/TypeAny.cc mars/TypeAny.h mars/TypeDate.cc mars/TypeDate.h mars/TypeEnum.cc mars/TypeEnum.h mars/TypeExpver.cc mars/TypeExpver.h mars/TypeFloat.cc mars/TypeFloat.h mars/TypeInteger.cc mars/TypeInteger.h mars/TypeLowercase.cc mars/TypeLowercase.h mars/TypeMixed.cc mars/TypeMixed.h mars/TypeParam.cc mars/TypeParam.h mars/TypeRange.cc mars/TypeRange.h mars/TypeRegex.cc mars/TypeRegex.h mars/TypesFactory.cc mars/TypesFactory.h mars/TypeTime.cc mars/TypeTime.h mars/TypeToByList.h mars/TypeToByListQuantile.cc mars/TypeToByListQuantile.h tool/MetkitTool.cc tool/MetkitTool.h fields/FieldIndex.cc fields/FieldIndex.h fields/FieldIndexList.cc fields/FieldIndexList.h fields/SimpleFieldIndex.cc fields/SimpleFieldIndex.h hypercube/HyperCube.cc hypercube/HyperCube.h hypercube/HyperCubePayloaded.h api/metkit_c.cc api/metkit_c.h ) list( APPEND metkit_persistent_srcs mars/Param.cc mars/Param.h mars/Param mars/StepRange.cc mars/StepRange.h mars/StepRange ) list( APPEND metkit_srcs ${metkit_persistent_srcs} ) if ( HAVE_GRIB ) list( APPEND metkit_srcs pointdb/bits.h pointdb/DataSource.cc pointdb/DataSource.h pointdb/FieldIndexer.cc pointdb/FieldIndexer.h pointdb/GribDataSource.cc pointdb/GribDataSource.h pointdb/GribFieldInfo.cc pointdb/GribFieldInfo.h pointdb/GribHandleDataSource.cc pointdb/GribHandleDataSource.h pointdb/masks.h pointdb/PointIndex.cc pointdb/PointIndex.h codes/BUFRDecoder.cc codes/BUFRDecoder.h codes/GRIBDecoder.cc codes/GRIBDecoder.h codes/CodesContent.cc codes/CodesContent.h codes/BufrContent.cc codes/BufrContent.h codes/MallocCodesContent.cc codes/MallocCodesContent.h codes/CodesSplitter.cc codes/CodesSplitter.h codes/GribAccessor.cc codes/GribAccessor.h codes/GribHandle.cc codes/GribHandle.h codes/GribIterator.cc codes/GribIterator.h codes/CodesHandleDeleter.h codes/api/CodesAPI.h codes/api/CodesAPI.cc codes/api/CodesTypes.h codes/api/CodesTypes.cc codes/api/KeyIterator.h codes/api/KeyIterator.cc codes/api/GeoIterator.h ) if( NOT eccodes_HAVE_GEOGRAPHY OR NOT eccodes_HAVE_ECKIT_GEO ) list( APPEND metkit_srcs codes/LibEccodes.cc codes/LibEccodes.h ) endif() set( grib_libs eccodes ) endif () if ( HAVE_ODB ) list( APPEND metkit_srcs odb/IdMapper.cc odb/IdMapper.h odb/OdbToRequest.cc odb/OdbToRequest.h odb/OdbMetadataDecoder.cc odb/OdbMetadataDecoder.h odb/OdbDecoder.cc odb/OdbContent.cc odb/OdbContent.h odb/OdbDecoder.h odb/OdbSplitter.cc odb/OdbSplitter.h ) set( odc_libs odccore ) endif() ecbuild_add_library( TARGET metkit INSTALL_HEADERS LISTED HEADER_DESTINATION ${INSTALL_INCLUDE_DIR}/metkit PERSISTENT ${metkit_persistent_srcs} SOURCES ${metkit_srcs} PUBLIC_INCLUDES $ $ $ # for metkit_version.h PRIVATE_LIBS "${odc_libs}" PUBLIC_LIBS eckit eckit_option ${grib_libs} ) metkit-1.16.0/src/metkit/api/000077500000000000000000000000001513171467200157405ustar00rootroot00000000000000metkit-1.16.0/src/metkit/api/metkit_c.cc000066400000000000000000000262131513171467200200520ustar00rootroot00000000000000#include "metkit_c.h" #include #include "eckit/runtime/Main.h" #include "metkit/mars/MarsExpansion.h" #include "metkit/mars/MarsRequest.h" #include "metkit/metkit_version.h" // --------------------------------------------------------------------------------------------------------------------- struct metkit_marsrequest_t : public metkit::mars::MarsRequest { using metkit::mars::MarsRequest::MarsRequest; metkit_marsrequest_t(metkit::mars::MarsRequest&& req) : metkit::mars::MarsRequest(std::move(req)) {} }; struct metkit_requestiterator_t { explicit metkit_requestiterator_t(std::vector&& vec) : vector_(std::move(vec)), current_(vector_.begin()) {} metkit_iterator_status_t next() { if (first_) { first_ = false; if (current_ != vector_.end()) { return METKIT_ITERATOR_SUCCESS; } } if (current_ == vector_.end()) { return METKIT_ITERATOR_COMPLETE; } ++current_; return current_ == vector_.end() ? METKIT_ITERATOR_COMPLETE : METKIT_ITERATOR_SUCCESS; } // Note: expected to call next() before calling current() metkit_iterator_status_t current(metkit_marsrequest_t* out) { if (first_ || current_ == vector_.end()) { return METKIT_ITERATOR_ERROR; } *out = std::move(*current_); return METKIT_ITERATOR_SUCCESS; } private: bool first_ = true; std::vector vector_; std::vector::iterator current_; }; // --------------------------------------------------------------------------------------------------------------------- /// @note: Unlike metkit_requestiterator_t, lifetime of the char* returned from this iterator are have the same as the /// iterator's lifetime. struct metkit_paramiterator_t { metkit_paramiterator_t(std::vector vec) : vector_(vec), current_(vector_.begin()) {} metkit_iterator_status_t next() { if (first_) { first_ = false; if (current_ != vector_.end()) { return METKIT_ITERATOR_SUCCESS; } } if (current_ == vector_.end()) { return METKIT_ITERATOR_COMPLETE; } ++current_; return current_ == vector_.end() ? METKIT_ITERATOR_COMPLETE : METKIT_ITERATOR_SUCCESS; } // Note: expected to call next() before calling current() metkit_iterator_status_t current(const char** out) const { if (first_ || current_ == vector_.end()) { return METKIT_ITERATOR_ERROR; } *out = current_->c_str(); return METKIT_ITERATOR_SUCCESS; } bool first_ = true; std::vector vector_; std::vector::const_iterator current_; }; // --------------------------------------------------------------------------------------------------------------------- // ERROR HANDLING static thread_local std::string g_current_error_string; const char* metkit_get_error_string(metkit_error_t err) { switch (err) { case METKIT_SUCCESS: return "Success"; case METKIT_ERROR: case METKIT_ERROR_USER: case METKIT_ERROR_ASSERT: return g_current_error_string.c_str(); default: return ""; } } metkit_error_t innerWrapFn(std::function f) { return f(); } metkit_error_t innerWrapFn(std::function f) { f(); return METKIT_SUCCESS; } template [[nodiscard]] metkit_error_t tryCatch(FN&& fn) { try { return innerWrapFn(std::forward(fn)); } catch (const eckit::UserError& e) { g_current_error_string = e.what(); return METKIT_ERROR_USER; } catch (const eckit::AssertionFailed& e) { g_current_error_string = e.what(); return METKIT_ERROR_ASSERT; } catch (const eckit::Exception& e) { g_current_error_string = e.what(); return METKIT_ERROR; } catch (const std::exception& e) { g_current_error_string = e.what(); return METKIT_ERROR_UNKNOWN; } catch (...) { return METKIT_ERROR_UNKNOWN; } } // ----------------------------------------------------------------------------- // HELPERS // ----------------------------------------------------------------------------- metkit_error_t metkit_initialise() { return tryCatch([] { static bool initialised = false; if (initialised) { eckit::Log::warning() << "Initialising Metkit library twice" << std::endl; } if (!initialised) { const char* argv[2] = {"metkit-api", nullptr}; eckit::Main::initialise(1, const_cast(argv)); initialised = true; } }); } // ----------------------------------------------------------------------------- // PARSING // ----------------------------------------------------------------------------- metkit_error_t metkit_parse_marsrequests(const char* str, metkit_requestiterator_t** requests, bool strict) { return tryCatch([requests, str, strict] { ASSERT(requests); ASSERT(str); std::istringstream in(str); *requests = new metkit_requestiterator_t(metkit::mars::MarsRequest::parse(in, strict)); }); } metkit_error_t metkit_parse_marsrequest(const char* str, metkit_marsrequest_t* request, bool strict) { return tryCatch([request, str, strict] { ASSERT(request); ASSERT(str); *request = metkit::mars::MarsRequest::parse(str, strict); }); } // ----------------------------------------------------------------------------- // REQUEST // ----------------------------------------------------------------------------- metkit_error_t metkit_marsrequest_new(metkit_marsrequest_t** request) { return tryCatch([request] { ASSERT(request); *request = new metkit_marsrequest_t(); }); } metkit_error_t metkit_marsrequest_delete(const metkit_marsrequest_t* request) { return tryCatch([request] { delete request; }); } metkit_error_t metkit_marsrequest_set(metkit_marsrequest_t* request, const char* param, const char* values[], int numValues) { return tryCatch([request, param, values, numValues] { ASSERT(request); ASSERT(param); ASSERT(values); std::string param_str(param); std::vector values_vec; values_vec.reserve(numValues); std::copy(values, values + numValues, std::back_inserter(values_vec)); request->values(param_str, values_vec); }); } metkit_error_t metkit_marsrequest_set_one(metkit_marsrequest_t* request, const char* param, const char* value) { return metkit_marsrequest_set(request, param, &value, 1); } metkit_error_t metkit_marsrequest_set_verb(metkit_marsrequest_t* request, const char* verb) { return tryCatch([request, verb] { ASSERT(request); ASSERT(verb); request->verb(verb); }); } metkit_error_t metkit_marsrequest_verb(const metkit_marsrequest_t* request, const char** verb) { return tryCatch([request, verb] { ASSERT(request); ASSERT(verb); *verb = request->verb().c_str(); }); } metkit_error_t metkit_marsrequest_has_param(const metkit_marsrequest_t* request, const char* param, bool* has) { return tryCatch([request, param, has] { ASSERT(request); ASSERT(param); ASSERT(has); *has = request->has(param); }); } metkit_error_t metkit_marsrequest_params(const metkit_marsrequest_t* request, metkit_paramiterator_t** params) { return tryCatch([request, params] { ASSERT(request); ASSERT(params); *params = new metkit_paramiterator_t(request->params()); }); } metkit_error_t metkit_marsrequest_count_values(const metkit_marsrequest_t* request, const char* param, size_t* count) { return tryCatch([request, param, count] { ASSERT(request); ASSERT(param); ASSERT(count); *count = request->countValues(param); }); } metkit_error_t metkit_marsrequest_value(const metkit_marsrequest_t* request, const char* param, int index, const char** value) { return tryCatch([request, param, index, value] { ASSERT(request); ASSERT(param); ASSERT(value); *value = request->values(param, false)[index].c_str(); }); } metkit_error_t metkit_marsrequest_expand(const metkit_marsrequest_t* request, bool inherit, bool strict, metkit_marsrequest_t* expandedRequest) { return tryCatch([request, expandedRequest, inherit, strict] { ASSERT(request); ASSERT(expandedRequest); ASSERT(expandedRequest->empty()); metkit::mars::MarsExpansion expand(inherit, strict); *expandedRequest = expand.expand(*request); }); } metkit_error_t metkit_marsrequest_merge(metkit_marsrequest_t* request, const metkit_marsrequest_t* otherRequest) { return tryCatch([request, otherRequest] { ASSERT(request); ASSERT(otherRequest); request->merge(*otherRequest); }); } void metkit_string_delete(const char* str) { delete[] str; } // ----------------------------------------------------------------------------- // REQUEST ITERATOR // ----------------------------------------------------------------------------- metkit_error_t metkit_requestiterator_delete(const metkit_requestiterator_t* it) { return tryCatch([it] { delete it; }); } metkit_iterator_status_t metkit_requestiterator_next(metkit_requestiterator_t* it) { if (!it) { return METKIT_ITERATOR_ERROR; } return it->next(); } metkit_iterator_status_t metkit_requestiterator_current(metkit_requestiterator_t* it, metkit_marsrequest_t* request) { if (!it || !request || !request->empty()) { return METKIT_ITERATOR_ERROR; } return it->current(request); } // ----------------------------------------------------------------------------- // PARAM ITERATOR // ----------------------------------------------------------------------------- metkit_error_t metkit_paramiterator_delete(const metkit_paramiterator_t* it) { return tryCatch([it] { delete it; }); } metkit_iterator_status_t metkit_paramiterator_next(metkit_paramiterator_t* it) { if (!it) { return METKIT_ITERATOR_ERROR; } return it->next(); } metkit_iterator_status_t metkit_paramiterator_current(const metkit_paramiterator_t* it, const char** param) { if (!it || !param) { return METKIT_ITERATOR_ERROR; } return it->current(param); } // --------------------------------------------------------------------------------------------------------------------- // Bridge between C and C++ const metkit::mars::MarsRequest& metkit::mars::MarsRequest::fromOpaque(const metkit_marsrequest_t* request) { return *static_cast(request); } // --------------------------------------------------------------------------------------------------------------------- metkit-1.16.0/src/metkit/api/metkit_c.h000066400000000000000000000226171513171467200177200ustar00rootroot00000000000000#pragma once #include #include #ifdef __cplusplus extern "C" { #endif /* --------------------------------------------------------------------------------------------------------------------- * TYPES * -----*/ struct metkit_marsrequest_t; typedef struct metkit_marsrequest_t metkit_marsrequest_t; struct metkit_requestiterator_t; /** RequestIterator for iterating over vector of Request instances */ typedef struct metkit_requestiterator_t metkit_requestiterator_t; struct metkit_paramiterator_t; /** Iterator for iterating over parameters in Request */ typedef struct metkit_paramiterator_t metkit_paramiterator_t; /* --------------------------------------------------------------------------------------------------------------------- * ERROR HANDLING * -------------- */ typedef enum metkit_error_values_t { METKIT_SUCCESS = 0, /* Operation succeded. */ METKIT_ERROR = 1, /* Operation failed. */ METKIT_ERROR_UNKNOWN = 2, /* Failed with an unknown error. */ METKIT_ERROR_USER = 3, /* Failed with an user error. */ METKIT_ERROR_ASSERT = 4 /* Failed with an assert() */ } metkit_error_t; typedef enum metkit_iterator_status_t { METKIT_ITERATOR_SUCCESS = 0, /* Operation succeded. */ METKIT_ITERATOR_COMPLETE = 1, /* All elements have been returned */ METKIT_ITERATOR_ERROR = 2 /* Operation failed. */ } metkit_iterator_status_t; const char* metkit_get_error_string(enum metkit_error_values_t err); /* ----------------------------------------------------------------------------- * HELPERS * ------- */ /** * @brief Get metkit version. * * @return const char* version string */ const char* metkit_version(); /** * @brief Get metkit git sha1 version. * * @return const char* git sha1 version string */ const char* metkit_git_sha1(); /** * @brief Initialise Main() context. * * @note This is ONLY required when Main() is NOT initialised, such as loading * the MetKit as shared library in Python. * @return metkit_error_t Error code */ metkit_error_t metkit_initialise(); /* --------------------------------------------------------------------------------------------------------------------- * PARSING * --- */ /** * Parse MARS requests into RequestIterator of Request instances. Resulting RequestIterator * must be deallocated with metkit_delete_requestiterator * @param str MARS requests * @param[out] requests Allocates RequestIterator object * @return metkit_error_t Error code */ metkit_error_t metkit_parse_marsrequests(const char* str, metkit_requestiterator_t** requests, bool strict); /** * Parse MARS request into Request instance * @note will error if request expands to multiple requests: use metkit_parse_marsrequests instead * @param str MARS request * @param[out] request Request instance * @param strict if true, raise error rather than warning on invalid values * @return metkit_error_t Error code */ metkit_error_t metkit_parse_marsrequest(const char* str, metkit_marsrequest_t* request, bool strict); /* --------------------------------------------------------------------------------------------------------------------- * REQUEST * --- */ /** Allocates new Request object. Must be deallocated with mekit_delete_request * @param[out] request new Request instance * @return metkit_error_t Error code */ metkit_error_t metkit_marsrequest_new(metkit_marsrequest_t** request); /** Deallocates Request object and associated resources. * @param request Request instance * @return metkit_error_t Error code */ metkit_error_t metkit_marsrequest_delete(const metkit_marsrequest_t* request); /** Add parameter and values to request * @param request Request instance * @param param parameter name * @param values array of values for parameter * @param numValues number of values * @return metkit_error_t Error code */ metkit_error_t metkit_marsrequest_set(metkit_marsrequest_t* request, const char* param, const char* values[], int numValues); /** Add parameter and values to request * @param request Request instance * @param param parameter name * @param values value to add * @return metkit_error_t Error code */ metkit_error_t metkit_marsrequest_set_one(metkit_marsrequest_t* request, const char* param, const char* value); /** Set verb in Request object * @param request Request instance * @param verb verb to set * @return metkit_error_t Error code */ metkit_error_t metkit_marsrequest_set_verb(metkit_marsrequest_t* request, const char* verb); /** Returns the verb in Request object * @param request Request instance * @param[out] verb verb in request * @return metkit_error_t Error code */ metkit_error_t metkit_marsrequest_verb(const metkit_marsrequest_t* request, const char** verb); /** Returns whether parameter is in Request object * @param request Request instance * @param param parameter name * @param[out] has whether parameter exists in request * @return metkit_error_t Error code */ metkit_error_t metkit_marsrequest_has_param(const metkit_marsrequest_t* request, const char* param, bool* has); /** Returns parameter iterator for Request object * Must be deallocated with metkit_paramiterator_delete * @note: The strings obtained from next() are owned by the iterator and should be copied if they need to outlive it. * @param request Request instance * @param[out] params parameter iterator * @return metkit_error_t Error code */ metkit_error_t metkit_marsrequest_params(const metkit_marsrequest_t* request, metkit_paramiterator_t** params); /** Returns number of values for specific parameter in Request object * @param request Request instance * @param param parameter name in request * @param[out] count number of values for param in request * @return metkit_error_t Error code */ metkit_error_t metkit_marsrequest_count_values(const metkit_marsrequest_t* request, const char* param, size_t* count); /** Returns value for specific parameter and index in Request object * @param request Request instance * @param param parameter name in request * @param index index of value to retrieve for param in request * @param[out] value retrieved value * @return metkit_error_t Error code */ metkit_error_t metkit_marsrequest_value(const metkit_marsrequest_t* request, const char* param, int index, const char** value); /** Populates empty Request object by expanding existing request * @param request Request instance to be expanded * @param inherit if true, populate expanded request with default values * @param strict it true, raise error rather than warning on invalid values * @param[out] expandedRequest empty Request instance to be populated * @return metkit_error_t Error code */ metkit_error_t metkit_marsrequest_expand(const metkit_marsrequest_t* request, bool inherit, bool strict, metkit_marsrequest_t* expandedRequest); /** Merges other Request object into existing request * @param request Request instance to contain result of merge * @param otherRequest other Request instance to merge * @return metkit_error_t Error code */ metkit_error_t metkit_marsrequest_merge(metkit_marsrequest_t* request, const metkit_marsrequest_t* otherRequest); /* --------------------------------------------------------------------------------------------------------------------- * REQUEST ITERATOR * --- */ /** Deallocates RequestIterator object and associated resources. * @param it RequestIterator instance * @return metkit_error_t Error code */ metkit_error_t metkit_requestiterator_delete(const metkit_requestiterator_t* it); /** Moves to the next Request element in RequestIterator * @param it RequestIterator instance * @return metkit_iterator_status_t Status of iterator */ // metkit_error_t metkit_requestiterator_next(metkit_requestiterator_t* it); metkit_iterator_status_t metkit_requestiterator_next(metkit_requestiterator_t* it); /** Populates empty Request object with data from current element in RequestIterator * @param it RequestIterator instance * @param request empty Request instance to populate with data * @return metkit_iterator_status_t Status of iterator * @note must call metkit_requestiterator_next before calling metkit_requestiterator_current. * * Example usage: * while (metkit_requestiterator_next(it) == METKIT_ITERATOR_SUCCESS) { * metkit_marsrequest_t* req{}; * metkit_marsrequest_new(&req); * metkit_requestiterator_current(it, req); * // use req ... * } */ metkit_iterator_status_t metkit_requestiterator_current(metkit_requestiterator_t* it, metkit_marsrequest_t* request); /* --------------------------------------------------------------------------------------------------------------------- * PARAMETER ITERATOR * --- */ /** Deallocates ParamIterator object and the char* strings it owns. * @param it ParamIterator instance * @return metkit_error_t Error code */ metkit_error_t metkit_paramiterator_delete(const metkit_paramiterator_t* it); /** Moves to the next parameter in ParamIterator * @param it ParamIterator instance * @return metkit_iterator_status_t Status of iterator */ metkit_iterator_status_t metkit_paramiterator_next(metkit_paramiterator_t* it); /** Returns current parameter in ParamIterator * @param it ParamIterator instance * @param[out] param current parameter * @return metkit_iterator_status_t Status of iterator */ metkit_iterator_status_t metkit_paramiterator_current(const metkit_paramiterator_t* it, const char** param); #ifdef __cplusplus } #endif metkit-1.16.0/src/metkit/codes/000077500000000000000000000000001513171467200162645ustar00rootroot00000000000000metkit-1.16.0/src/metkit/codes/BUFRDecoder.cc000066400000000000000000000116651513171467200206300ustar00rootroot00000000000000/* * (C) Copyright 1996- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ #include #include #include "eckit/config/Resource.h" #include "eckit/message/Message.h" #include "eckit/parser/YAMLParser.h" #include "metkit/codes/BUFRDecoder.h" #include "metkit/codes/api/CodesAPI.h" #include "metkit/codes/api/CodesTypes.h" #include "metkit/config/LibMetkit.h" #include "metkit/mars/MarsRequest.h" #include "eckit/exception/Exceptions.h" #include "eccodes.h" namespace metkit { namespace codes { //---------------------------------------------------------------------------------------------------------------------- static std::map subtypes_; static pthread_once_t once = PTHREAD_ONCE_INIT; static void readTable() { eckit::PathName bufrSubtypesPath = eckit::Resource("bufrSubtypesPath;$BUFR_SUBTYPES_PATH", LibMetkit::bufrSubtypesYamlFile()); const eckit::Value bufrSubtypes = eckit::YAMLParser::decodeFile(bufrSubtypesPath); const eckit::Value subtypes = bufrSubtypes["subtypes"]; ASSERT(subtypes.isList()); for (size_t i = 0; i < subtypes.size(); ++i) { const eckit::Value s = subtypes[i]; ASSERT(s.isList()); ASSERT(s.size() == 2); subtypes_[s[0]] = s[1]; } } bool BUFRDecoder::typeBySubtype(long subtype, long& type) { pthread_once(&once, readTable); auto s = subtypes_.find(subtype); if (s != subtypes_.end()) { type = s->second; return true; } return false; } //---------------------------------------------------------------------------------------------------------------------- bool BUFRDecoder::match(const eckit::message::Message& msg) const { size_t len = msg.length(); const char* p = static_cast(msg.data()); return len >= 4 and p[0] == 'B' and p[1] == 'U' and p[2] == 'F' and p[3] == 'R'; } //---------------------------------------------------------------------------------------------------------------------- void BUFRDecoder::getMetadata(const eckit::message::Message& msg, eckit::message::MetadataGatherer& gather, const eckit::message::GetMetadataOptions& options) const { auto h(codesHandleFromMessage({static_cast(msg.data()), msg.length()})); /* // BUFR Performance improvement: https://confluence.ecmwf.int/display/UDOC/Performance+improvement+by+skipping+some+keys+-+ecCodes+BUFR+FAQ if ((unsigned long)(options.filter & eckit::message::MetadataFilter::IncludeExtraKeyAttributes) != 0) { CODES_CHECK(codes_set_long(h.get(), "skipExtraKeyAttributes", 1), 0); } */ // we need to instruct ecCodes to unpack the data values: // https://confluence.ecmwf.int/display/ECC/bufr_keys_iterator h->set("unpack", 1); for (auto& k : h->keys()) { auto name = k.name(); if (name == "subsetNumber") { continue; } /* get key size to see if it is an array */ if (h->size(name) != 1) { continue; } switch (options.valueRepresentation) { case eckit::message::ValueRepresentation::String: { gather.setValue(name, k.getString()); break; } case eckit::message::ValueRepresentation::Native: { std::visit( [&](auto&& v) { using Type = std::decay_t; if constexpr (std::is_same_v || std::is_arithmetic_v) { gather.setValue(name, std::forward(v)); } }, k.get()); break; } } } } //---------------------------------------------------------------------------------------------------------------------- eckit::Buffer BUFRDecoder::decode(const eckit::message::Message& msg) const { std::size_t size = msg.getSize("numericValues"); eckit::Buffer buf(size * sizeof(double)); msg.getDoubleArray("numericValues", reinterpret_cast(buf.data()), size); return buf; } //---------------------------------------------------------------------------------------------------------------------- void BUFRDecoder::print(std::ostream& s) const { s << "BUFRDecoder[]"; } //---------------------------------------------------------------------------------------------------------------------- static BUFRDecoder bufrDecoder; //---------------------------------------------------------------------------------------------------------------------- } // namespace codes } // namespace metkit metkit-1.16.0/src/metkit/codes/BUFRDecoder.h000066400000000000000000000026041513171467200204630ustar00rootroot00000000000000/* * (C) Copyright 1996- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ /// @author Baudouin Raoult /// @date Jun 2020 #pragma once #include "eckit/message/Decoder.h" #include "eckit/message/Message.h" #include "eckit/io/Buffer.h" namespace metkit { namespace codes { //---------------------------------------------------------------------------------------------------------------------- class BUFRDecoder : public eckit::message::MessageDecoder { public: // methods static bool typeBySubtype(long subtype, long& type); private: // methods bool match(const eckit::message::Message&) const override; void print(std::ostream&) const override; void getMetadata(const eckit::message::Message& msg, eckit::message::MetadataGatherer&, const eckit::message::GetMetadataOptions&) const override; eckit::Buffer decode(const eckit::message::Message& msg) const override; }; //---------------------------------------------------------------------------------------------------------------------- } // namespace codes } // namespace metkit metkit-1.16.0/src/metkit/codes/BufrContent.cc000066400000000000000000000032141513171467200210240ustar00rootroot00000000000000/* * (C) Copyright 2017- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ /// @author Baudouin Raoult /// @author Emanuele Danovaro /// @date Mar 2022 #include "metkit/codes/BufrContent.h" #include "metkit/codes/GribHandle.h" #include "eccodes.h" namespace metkit { namespace codes { //---------------------------------------------------------------------------------------------------------------------- BufrContent::BufrContent(codes_handle* handle, bool delete_handle) : CodesContent(handle, delete_handle) {} BufrContent::BufrContent(const codes_handle* handle) : BufrContent(const_cast(handle), false) {} BufrContent::~BufrContent() {} //---------------------------------------------------------------------------------------------------------------------- void BufrContent::transform(const eckit::OrderedStringDict& dict) { std::vector values; for (auto& kv : dict) { codes_values v; v.name = kv.first.c_str(); v.long_value = std::stol(kv.second); v.type = GRIB_TYPE_LONG; values.push_back(v); } CODES_CALL(codes_set_values(handle_, values.data(), values.size())); } //---------------------------------------------------------------------------------------------------------------------- } // namespace codes } // namespace metkit metkit-1.16.0/src/metkit/codes/BufrContent.h000066400000000000000000000022101513171467200206610ustar00rootroot00000000000000/* * (C) Copyright 2017- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ /// @author Baudouin Raoult /// @author Emanuele Danovaro /// @date Mar 2022 #pragma once #include "metkit/codes/CodesContent.h" namespace metkit { namespace codes { //---------------------------------------------------------------------------------------------------------------------- class BufrContent : public CodesContent { public: BufrContent(codes_handle* handle, bool delete_handle); explicit BufrContent(const codes_handle* handle); ~BufrContent(); protected: using CodesContent::transform; void transform(const eckit::OrderedStringDict& dict) override; }; //---------------------------------------------------------------------------------------------------------------------- } // namespace codes } // namespace metkit metkit-1.16.0/src/metkit/codes/CodesContent.cc000066400000000000000000000150071513171467200211660ustar00rootroot00000000000000/* * (C) Copyright 2017- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ /// @author Baudouin Raoult /// @date Jun 2020 #include "metkit/codes/CodesContent.h" #include "eccodes.h" #include "eckit/exception/Exceptions.h" #include "eckit/io/DataHandle.h" #include "eckit/io/MemoryHandle.h" #include "eckit/memory/Zero.h" #include "metkit/codes/GribHandle.h" namespace metkit { namespace codes { //---------------------------------------------------------------------------------------------------------------------- CodesContent::CodesContent(codes_handle* handle, bool delete_handle) : handle_(handle), delete_handle_(delete_handle) { ASSERT(handle_); } CodesContent::CodesContent(const codes_handle* handle) : CodesContent(const_cast(handle), false) {} CodesContent::~CodesContent() { if (delete_handle_) { codes_handle_delete(handle_); } } //---------------------------------------------------------------------------------------------------------------------- size_t CodesContent::length() const { size_t size; const void* data; CODES_CALL(codes_get_message(handle_, &data, &size)); return size; } //---------------------------------------------------------------------------------------------------------------------- void CodesContent::write(eckit::DataHandle& handle) const { size_t size; const void* data; CODES_CALL(codes_get_message(handle_, &data, &size)); if (handle.write(data, size) != size) { std::ostringstream oss; oss << "Write error to data handle " << handle; throw eckit::WriteError(oss.str(), Here()); } } //---------------------------------------------------------------------------------------------------------------------- eckit::DataHandle* CodesContent::readHandle() const { size_t size; const void* data; CODES_CALL(codes_get_message(handle_, &data, &size)); return new eckit::MemoryHandle(data, size); } //---------------------------------------------------------------------------------------------------------------------- void CodesContent::print(std::ostream& s) const { s << "CodesContent[]"; } //---------------------------------------------------------------------------------------------------------------------- std::string CodesContent::getString(const std::string& key) const { char values[10240]; size_t len = sizeof(values); values[0] = 0; CODES_CALL(codes_get_string(handle_, key.c_str(), values, &len)); // ASSERT(err) return values; } //---------------------------------------------------------------------------------------------------------------------- long CodesContent::getLong(const std::string& key) const { long v = 0; CODES_CALL(codes_get_long(handle_, key.c_str(), &v)); return v; } //---------------------------------------------------------------------------------------------------------------------- double CodesContent::getDouble(const std::string& key) const { double v = 0; CODES_CALL(codes_get_double(handle_, key.c_str(), &v)); return v; } //---------------------------------------------------------------------------------------------------------------------- void CodesContent::getDoubleArray(const std::string& key, std::vector& values) const { size_t size = 0; CODES_CALL(codes_get_size(handle_, key.c_str(), &size)); size_t count = size; values.resize(count); CODES_CALL(codes_get_double_array(handle_, key.c_str(), &values[0], &count)); ASSERT(count == size); } //---------------------------------------------------------------------------------------------------------------------- void CodesContent::getFloatArray(const std::string& key, std::vector& values) const { size_t size = 0; CODES_CALL(codes_get_size(handle_, key.c_str(), &size)); size_t count = size; values.resize(count); CODES_CALL(codes_get_float_array(handle_, key.c_str(), &values[0], &count)); ASSERT(count == size); } //---------------------------------------------------------------------------------------------------------------------- size_t CodesContent::getSize(const std::string& key) const { size_t size = 0; CODES_CALL(codes_get_size(handle_, key.c_str(), &size)); return size; } //---------------------------------------------------------------------------------------------------------------------- void CodesContent::getDoubleArray(const std::string& key, double* data, size_t len) const { size_t count = len; CODES_CALL(codes_get_double_array(handle_, key.c_str(), data, &count)); ASSERT(count == len); } //---------------------------------------------------------------------------------------------------------------------- void CodesContent::getFloatArray(const std::string& key, float* data, size_t len) const { size_t count = len; CODES_CALL(codes_get_float_array(handle_, key.c_str(), data, &count)); ASSERT(count == len); } //---------------------------------------------------------------------------------------------------------------------- void CodesContent::transform(const eckit::OrderedStringDict& dict) { std::vector values; values.reserve(dict.size()); for (auto& kv : dict) { codes_values v; v.name = kv.first.c_str(); v.string_value = kv.second.c_str(); v.type = GRIB_TYPE_STRING; values.push_back(v); } CODES_CALL(codes_set_values(handle_, values.data(), values.size())); } //---------------------------------------------------------------------------------------------------------------------- eckit::Offset CodesContent::offset() const { long pos; CODES_CALL(codes_get_long(handle_, "offset", &pos)); return pos; } //---------------------------------------------------------------------------------------------------------------------- const codes_handle* CodesContent::codesHandle() const { return handle_; } //---------------------------------------------------------------------------------------------------------------------- const void* CodesContent::data() const { size_t size; const void* data; CODES_CALL(codes_get_message(handle_, &data, &size)); return data; } } // namespace codes } // namespace metkit metkit-1.16.0/src/metkit/codes/CodesContent.h000066400000000000000000000042521513171467200210300ustar00rootroot00000000000000/* * (C) Copyright 2017- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ /// @author Baudouin Raoult /// @date Jun 2020 #pragma once #include "eckit/message/MessageContent.h" typedef struct grib_handle codes_handle; namespace metkit { namespace codes { //---------------------------------------------------------------------------------------------------------------------- class CodesContent : public eckit::message::MessageContent { public: CodesContent(codes_handle* handle, bool delete_handle); explicit CodesContent(const codes_handle* handle); ~CodesContent(); protected: codes_handle* handle_; using eckit::message::MessageContent::transform; void transform(const eckit::OrderedStringDict&) override; private: bool delete_handle_; size_t length() const override; void write(eckit::DataHandle& handle) const override; eckit::DataHandle* readHandle() const override; void print(std::ostream& s) const override; std::string getString(const std::string& key) const override; long getLong(const std::string& key) const override; double getDouble(const std::string& key) const override; void getDoubleArray(const std::string& key, std::vector& values) const override; void getFloatArray(const std::string& key, std::vector& values) const override; size_t getSize(const std::string& key) const override; void getDoubleArray(const std::string& key, double* data, size_t lenExpected) const override; void getFloatArray(const std::string& key, float* data, size_t lenExpected) const override; eckit::Offset offset() const override; const codes_handle* codesHandle() const; const void* data() const override; }; //---------------------------------------------------------------------------------------------------------------------- } // namespace codes } // namespace metkit metkit-1.16.0/src/metkit/codes/CodesHandleDeleter.h000066400000000000000000000023101513171467200221070ustar00rootroot00000000000000/* * (C) Copyright 2022- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ /// @author Philipp Geier /// @author Simon Smart /// @date Nov 2022 #pragma once #include #include //---------------------------------------------------------------------------------------------------------------------- namespace std { template <> struct default_delete { void operator()(codes_handle* h) { ::codes_handle_delete(h); } }; template <> struct default_delete { void operator()(codes_keys_iterator* it) { ::codes_keys_iterator_delete(it); } }; template <> struct default_delete { void operator()(codes_bufr_keys_iterator* it) { ::codes_bufr_keys_iterator_delete(it); } }; } // namespace std //---------------------------------------------------------------------------------------------------------------------- metkit-1.16.0/src/metkit/codes/CodesSplitter.cc000066400000000000000000000071401513171467200213610ustar00rootroot00000000000000/* * (C) Copyright 1996- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ #include "metkit/codes/CodesSplitter.h" #include "eccodes.h" #include "eckit/config/Resource.h" #include "eckit/io/PeekHandle.h" #include "eckit/log/Log.h" #include "eckit/message/Message.h" #include "metkit/codes/GribHandle.h" #include "metkit/codes/MallocCodesContent.h" namespace metkit { namespace codes { //---------------------------------------------------------------------------------------------------------------------- CodesSplitter::CodesSplitter(eckit::PeekHandle& handle) : Splitter(handle) {} CodesSplitter::~CodesSplitter() {} static long readcb(void* data, void* buffer, long len) { eckit::DataHandle* handle = reinterpret_cast(data); try { long r = handle->read(buffer, len); // DataHandle is returning 0 on EOF. Codes expects -1 for EOF. return (r == 0) ? -1 : r; } catch (const std::exception& e) { eckit::Log::error() << "Exception thrown in CodesSplitter::readcb callback: " << e.what() << "." << std::endl << " This may cause unexpected behaviour. Returning -2 instead." << std::endl; // Return negative other from -1 to signalize error. return -2; } catch (...) { eckit::Log::error() << "Unknown exception occured in CodesSplitter::readcb callback. This may cause unexpected " "behaviour. Returning -2 instead." << std::endl; // Return negative other from -1 to signalize error. return -2; } } eckit::message::Message CodesSplitter::next() { size_t size; int err = 0; void* data = wmo_read_any_from_stream_malloc(&handle_, &readcb, &size, &err); if (err != 0 and err != GRIB_END_OF_FILE) { if (data) { ::free(data); } if (err == GRIB_WRONG_LENGTH && handle_.canSeek()) { eckit::Offset off = handle_.position() - eckit::Length(size); handle_.seek((off < eckit::Offset(0) ? eckit::Offset(0) : off) + eckit::Offset(4)); } CODES_CALL(err); } if (!data) { return eckit::message::Message(); } return eckit::message::Message(new MallocCodesContent(data, size, 0)); } void CodesSplitter::print(std::ostream& s) const { s << "CodesSplitter[]"; } } // namespace codes } // namespace metkit //---------------------------------------------------------------------------------------------------------------------- namespace eckit { namespace message { template <> bool SplitterBuilder::match(eckit::PeekHandle& handle) const { unsigned char c0 = handle.peek(0); unsigned char c1 = handle.peek(1); unsigned char c2 = handle.peek(2); unsigned char c3 = handle.peek(3); if (c0 == 'G' and c1 == 'R' and c2 == 'I' and c3 == 'B') { return true; } if (c0 == 'B' and c1 == 'U' and c2 == 'F' and c3 == 'R') { return true; } if (c0 == 'B' and c1 == 'U' and c2 == 'D' and c3 == 'G') { return true; } if (c0 == 'T' and c1 == 'I' and c2 == 'D' and c3 == 'E') { return true; } return false; } } // namespace message } // namespace eckit static eckit::message::SplitterBuilder splitter; metkit-1.16.0/src/metkit/codes/CodesSplitter.h000066400000000000000000000020531513171467200212210ustar00rootroot00000000000000/* * (C) Copyright 1996- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ /// @author Baudouin Raoult /// @date Jun 2020 #pragma once #include "eckit/message/Splitter.h" namespace metkit { namespace codes { //---------------------------------------------------------------------------------------------------------------------- class CodesSplitter : public eckit::message::Splitter { public: CodesSplitter(eckit::PeekHandle&); ~CodesSplitter(); private: // methods eckit::message::Message next() override; void print(std::ostream&) const override; }; //---------------------------------------------------------------------------------------------------------------------- } // namespace codes } // namespace metkit metkit-1.16.0/src/metkit/codes/GRIBDecoder.cc000066400000000000000000000116041513171467200206060ustar00rootroot00000000000000/* * (C) Copyright 1996- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ #include "eckit/config/Resource.h" #include "eckit/io/Buffer.h" #include "eckit/message/Message.h" #include "eckit/serialisation/MemoryStream.h" #include "metkit/codes/GRIBDecoder.h" #include "metkit/codes/api/CodesAPI.h" #include #include #include "eccodes.h" namespace metkit { namespace codes { //---------------------------------------------------------------------------------------------------------------------- bool GRIBDecoder::match(const eckit::message::Message& msg) const { size_t len = msg.length(); const char* p = static_cast(msg.data()); return len >= 4 and ((p[0] == 'G' and p[1] == 'R' and p[2] == 'I' and p[3] == 'B') or (p[0] == 'T' and p[1] == 'I' and p[2] == 'D' and p[3] == 'E') or (p[0] == 'B' and p[1] == 'U' and p[2] == 'D' and p[3] == 'G')); } void GRIBDecoder::getMetadata(const eckit::message::Message& msg, eckit::message::MetadataGatherer& gather, const eckit::message::GetMetadataOptions& options) const { static std::string gribToRequestNamespace = eckit::Resource("gribToRequestNamespace", "mars"); std::string nameSpace = options.nameSpace ? *options.nameSpace : gribToRequestNamespace; auto h = codesHandleFromMessage({static_cast(msg.data()), msg.length()}); for (auto& k : h->keys(nameSpace)) { auto name = k.name(); if (name[0] == '_') continue; // skip silly underscores in GRIB /* get key size to see if it is an array */ if (h->size(name) != 1) { continue; } switch (options.valueRepresentation) { case eckit::message::ValueRepresentation::String: { gather.setValue(name, k.getString()); break; } case eckit::message::ValueRepresentation::Native: { // https://jira.ecmwf.int/browse/ECC-2166 if (name == "uuidOfHGrid") { // uuidOfHGrid returns size 1 although it contains 16 bytes gather.setValue(name, k.getString()); } else { std::visit( [&](auto&& v) { using Type = std::decay_t; if constexpr (std::is_same_v || std::is_arithmetic_v) { gather.setValue(name, std::forward(v)); } }, k.get()); } break; } } } // Explicit override for param (kludge for paramID handling) if (h->has("paramId")) { gather.setValue("param", h->getString("paramId")); } // Look for request embbeded in GRIB message if (h->has("localDefinitionNumber") && h->getLong("localDefinitionNumber") == 191) { /* TODO: Not grib2 compatible, but speed-up process */ if (h->has("freeFormData")) { auto buffer = h->getBytes("freeFormData"); eckit::MemoryStream s(buffer.data(), buffer.size()); int count; s >> count; // Number of requests ASSERT(count == 1); std::string tmp; s >> tmp; // verb s >> count; for (int i = 0; i < count; i++) { std::string keyword, value; int n; s >> keyword; std::transform(keyword.begin(), keyword.end(), keyword.begin(), tolower); s >> n; // Number of values ASSERT(n == 1); s >> value; std::transform(value.begin(), value.end(), value.begin(), tolower); gather.setValue(keyword, value); } } } } eckit::Buffer GRIBDecoder::decode(const eckit::message::Message& msg) const { std::size_t size = msg.getSize("values"); eckit::Buffer buf(size * sizeof(double)); msg.getDoubleArray("values", reinterpret_cast(buf.data()), size); return buf; } void GRIBDecoder::print(std::ostream& s) const { s << "GRIBDecoder[]"; } //---------------------------------------------------------------------------------------------------------------------- static GRIBDecoder gribDecoder; //---------------------------------------------------------------------------------------------------------------------- } // namespace codes } // namespace metkit metkit-1.16.0/src/metkit/codes/GRIBDecoder.h000066400000000000000000000024571513171467200204560ustar00rootroot00000000000000/* * (C) Copyright 2020- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ /// @author Baudouin Raoult /// @date Jun 2020 #pragma once #include "eckit/message/Decoder.h" #include "eckit/message/Message.h" #include "eckit/io/Buffer.h" namespace metkit::codes { //---------------------------------------------------------------------------------------------------------------------- class GRIBDecoder : public eckit::message::MessageDecoder { public: // methods private: // methods bool match(const eckit::message::Message&) const override; void print(std::ostream&) const override; void getMetadata(const eckit::message::Message& msg, eckit::message::MetadataGatherer&, const eckit::message::GetMetadataOptions&) const override; eckit::Buffer decode(const eckit::message::Message& msg) const override; }; //---------------------------------------------------------------------------------------------------------------------- } // namespace metkit::codes metkit-1.16.0/src/metkit/codes/GribAccessor.cc000066400000000000000000000063611513171467200211470ustar00rootroot00000000000000/* * (C) Copyright 1996- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ #include "metkit/codes/GribAccessor.h" #include "eccodes.h" #include "metkit/codes/GribHandle.h" namespace metkit { namespace grib { //---------------------------------------------------------------------------------------------------------------------- static void check_error_code(const std::string& name, int err, bool quiet = false) { if (err && !quiet) { eckit::Log::error() << "GribAccessor(" << name << "): " << codes_get_error_message(err) << std::endl; } } void GribAccessorBase::grib_get_value(const GribHandle& h, const std::string& name, double& x, bool quiet) const { x = 0; int err = codes_get_double(h.raw(), name.c_str(), &x); check_error_code(name, err, quiet); } void GribAccessorBase::grib_get_value(const GribHandle& h, const std::string& name, unsigned long& x, bool quiet) const { long y = 0; int err = codes_get_long(h.raw(), name.c_str(), &y); check_error_code(name, err, quiet); x = y; } void GribAccessorBase::grib_get_value(const GribHandle& h, const std::string& name, long& x, bool quiet) const { x = 0; int err = codes_get_long(h.raw(), name.c_str(), &x); check_error_code(name, err, quiet); } void GribAccessorBase::grib_get_value(const GribHandle& h, const std::string& name, bool& x, bool quiet) const { x = true; long xd = 0; int err = codes_get_long(h.raw(), name.c_str(), &xd); check_error_code(name, err, quiet); if (xd == 0) x = false; } void GribAccessorBase::grib_get_value(const GribHandle& h, const std::string& name, std::string& x, bool quiet) const { char buf[1024]; size_t s = sizeof(buf); buf[0] = 0; int err = codes_get_string(h.raw(), name.c_str(), buf, &s); check_error_code(name, err, quiet); x = buf; } void GribAccessorBase::grib_get_value(const GribHandle& h, const std::string& name, std::vector& x, bool quiet) const { int err = 0; size_t sz = 0; err = codes_get_size(h.raw(), name.c_str(), &sz); check_error_code(name, err, quiet); x.resize(sz); err = codes_get_long_array(h.raw(), name.c_str(), &x[0], &sz); check_error_code(name, err, quiet); ASSERT(x.size() == sz); } void GribAccessorBase::grib_get_value(const GribHandle& h, const std::string& name, std::vector& x, bool quiet) const { int err = 0; size_t sz = 0; err = codes_get_size(h.raw(), name.c_str(), &sz); check_error_code(name, err, quiet); x.resize(sz); err = codes_get_double_array(h.raw(), name.c_str(), &x[0], &sz); check_error_code(name, err, quiet); ASSERT(x.size() == sz); } //---------------------------------------------------------------------------------------------------------------------- } // namespace grib } // namespace metkit metkit-1.16.0/src/metkit/codes/GribAccessor.h000066400000000000000000000046501513171467200210100ustar00rootroot00000000000000/* * (C) Copyright 1996- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ #pragma once #include "eckit/exception/Exceptions.h" #include "eckit/log/Log.h" #include "metkit/codes/GribHandle.h" namespace metkit { namespace grib { //---------------------------------------------------------------------------------------------------------------------- class GribAccessorBase { protected: void grib_get_value(const GribHandle& h, const std::string& name, double& x, bool quiet = false) const; void grib_get_value(const GribHandle& h, const std::string& name, unsigned long& x, bool quiet = false) const; void grib_get_value(const GribHandle& h, const std::string& name, long& x, bool quiet = false) const; void grib_get_value(const GribHandle& h, const std::string& name, bool& x, bool quiet = false) const; void grib_get_value(const GribHandle& h, const std::string& name, std::string& x, bool quiet = false) const; void grib_get_value(const GribHandle& h, const std::string& name, std::vector& x, bool quiet = false) const; void grib_get_value(const GribHandle& h, const std::string& name, std::vector& x, bool quiet = false) const; }; //---------------------------------------------------------------------------------------------------------------------- template class GribAccessor : private GribAccessorBase { private: // members std::string name_; bool quiet_; public: // methods GribAccessor(const std::string& name, bool quiet = false) : name_(name), quiet_(quiet) {} T value(const GribHandle& h) const { T value; grib_get_value(h, name_, value, quiet_); return value; } T value(const GribHandle& h, T def) const { T value = def; grib_get_value(h, name_, value, true); return value; } T operator()(const GribHandle& h) const { return value(h); } T operator()(const GribHandle& h, T def) const { return value(h, def); } }; //---------------------------------------------------------------------------------------------------------------------- } // namespace grib } // namespace metkit metkit-1.16.0/src/metkit/codes/GribHandle.cc000066400000000000000000000116611513171467200205770ustar00rootroot00000000000000/* * (C) Copyright 1996- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ #include "metkit/codes/GribHandle.h" #include "eccodes.h" #include "eckit/exception/Exceptions.h" #include "eckit/io/DataHandle.h" #include "eckit/io/StdFile.h" #include "metkit/codes/GribAccessor.h" using namespace std; namespace metkit { namespace grib { //---------------------------------------------------------------------------------------------------------------------- void codes_call(int code, const char* msg, const eckit::CodeLocation& where) { if (code) { std::ostringstream os; os << msg << " : " << codes_get_error_message(code); throw eckit::Exception(os.str(), where); } } //---------------------------------------------------------------------------------------------------------------------- GribHandle::GribHandle(const eckit::PathName& path) : handle_(nullptr), owned_(true) { eckit::AutoStdFile f(path); int err = 0; codes_handle* h = codes_handle_new_from_file(nullptr, f, PRODUCT_GRIB, &err); if (err != 0) { std::ostringstream os; os << "GribHandle() failed to build from path " << path; throw eckit::Exception(os.str(), Here()); } ASSERT(h); handle_ = h; } GribHandle::GribHandle(codes_handle* h) : handle_(h), owned_(true) { ASSERT(h); } GribHandle::GribHandle(codes_handle& h) : handle_(&h), owned_(false) {} GribHandle::GribHandle(eckit::DataHandle& handle) : handle_(nullptr), owned_(true) { codes_handle* h = nullptr; int err = 0; FILE* f = handle.openf(); ASSERT(f); h = codes_handle_new_from_file(0, f, PRODUCT_GRIB, &err); CODES_CALL(err); ASSERT(h); handle_ = h; fclose(f); } GribHandle::GribHandle(eckit::DataHandle& handle, eckit::Offset offset) : handle_(nullptr), owned_(true) { codes_handle* h = nullptr; int err = 0; FILE* f = handle.openf(); ASSERT(f); fseek(f, offset, SEEK_SET); h = codes_handle_new_from_file(0, f, PRODUCT_GRIB, &err); CODES_CALL(err); ASSERT(h); handle_ = h; fclose(f); } GribHandle::~GribHandle() noexcept(false) { if (handle_ && owned_) { CODES_CALL(codes_handle_delete(handle_)); handle_ = nullptr; } } std::string GribHandle::geographyHash() const { // The following key is edition independent return GribAccessor("md5GridSection")(*this); } size_t GribHandle::getDataValuesSize() const { size_t count = 0; CODES_CALL(codes_get_size(raw(), "values", &count)); return count; } void GribHandle::getDataValues(double* values, const size_t& count) const { ASSERT(values); size_t n = count; CODES_CALL(codes_get_double_array(raw(), "values", values, &n)); ASSERT(n == count); } double* GribHandle::getDataValues(size_t& count) const { count = getDataValuesSize(); double* values = new double[count]; getDataValues(values, count); return values; } void GribHandle::setDataValues(const double* values, size_t count) { ASSERT(values); CODES_CALL(codes_set_double_array(raw(), "values", values, count)); } void GribHandle::dump(const eckit::PathName& path, const char* mode) const { eckit::StdFile f(path.localPath(), "w"); codes_dump_content(handle_, f, "mode", 0, 0); f.close(); } void GribHandle::write(const eckit::PathName& path, const char* mode) const { ASSERT(codes_write_message(handle_, path.localPath(), mode) == 0); } size_t GribHandle::write(eckit::DataHandle& handle) const { const void* message = nullptr; size_t length = 0; CODES_CALL(codes_get_message(raw(), &message, &length)); ASSERT(message); ASSERT(length); ASSERT(length = long(length)); ASSERT(handle.write(message, length) == long(length)); return length; } size_t GribHandle::length() const { const void* message = nullptr; size_t length = 0; CODES_CALL(codes_get_message(raw(), &message, &length)); return length; } size_t GribHandle::write(eckit::Buffer& buff) const { size_t len = buff.size(); CODES_CALL(codes_get_message_copy(raw(), buff, &len)); // will issue error if buffer too small return len; } GribHandle* GribHandle::clone() const { codes_handle* h = codes_handle_clone(raw()); if (!h) { throw eckit::WriteError(std::string("failed to clone output grib")); } return new GribHandle(h); } bool GribHandle::hasKey(const char* key) const { return (codes_is_defined(handle_, key) != 0); } //---------------------------------------------------------------------------------------------------------------------- } // namespace grib } // namespace metkit metkit-1.16.0/src/metkit/codes/GribHandle.h000066400000000000000000000066521513171467200204450ustar00rootroot00000000000000/* * (C) Copyright 1996- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ #pragma once #include "eckit/filesystem/PathName.h" #include "eckit/io/Buffer.h" #include "eckit/log/CodeLocation.h" #include "eckit/memory/NonCopyable.h" struct grib_handle; namespace eckit { class DataHandle; } namespace metkit { namespace grib { class GribMetaData; class GribAccessorBase; class GribMutatorBase; //---------------------------------------------------------------------------------------------------------------------- void codes_call(int code, const char* msg, const eckit::CodeLocation& where); #define CODES_CALL(a) metkit::grib::codes_call(a, #a, Here()) //---------------------------------------------------------------------------------------------------------------------- class GribHandle : private eckit::NonCopyable { public: // types /// constructor from file path, creates grib_handle and takes ownership /// @note currently this only handles local paths explicit GribHandle(const eckit::PathName&); /// constructor taking ownership of a grib_handle pointer GribHandle(grib_handle*); /// constructor not taking GribHandle(grib_handle&); /// constructor creating a grib_handle from a DataHandle explicit GribHandle(eckit::DataHandle&); // Constructor creating a grib_handle from a DataHandle starting from a given offset explicit GribHandle(eckit::DataHandle&, eckit::Offset); /// destructor will delete the grib_handle if we own it ~GribHandle() noexcept(false); public: // methods size_t length() const; // std::string gridType() const; std::string geographyHash() const; GribHandle* clone() const; // std::string shortName() const; // size_t numberOfPoints() const; size_t getDataValuesSize() const; double* getDataValues(size_t&) const; void getDataValues(double*, const size_t&) const; void setDataValues(const double*, size_t); size_t write(eckit::DataHandle&) const; size_t write(eckit::Buffer&) const; void write(const eckit::PathName&, const char* mode = "w") const; void dump(const eckit::PathName&, const char* mode = "debug") const; // double latitudeOfFirstGridPointInDegrees() const; // double longitudeOfFirstGridPointInDegrees() const; // double latitudeOfLastGridPointInDegrees() const; // double longitudeOfLastGridPointInDegrees() const; bool hasKey(const char*) const; operator const grib_handle*() const { return handle_; } protected: // methods friend class GribAccessorBase; friend class GribMutatorBase; friend class GribIterator; /// To be used by friends since this is rather dangerous /// Don't delete this pointer, use with care :) /// @returns the raw grib_handle so client code can call grib directly grib_handle* raw() const { return handle_; } /// Client code shouldn't care if GRIB edition long edition() const; private: // members grib_handle* handle_; bool owned_; }; //------------------------------------------------------------------------------------------------------ } // namespace grib } // namespace metkit metkit-1.16.0/src/metkit/codes/GribIterator.cc000066400000000000000000000021451513171467200211720ustar00rootroot00000000000000/* * (C) Copyright 1996- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ #include "metkit/codes/GribIterator.h" #include "eckit/exception/Exceptions.h" #include "metkit/codes/GribHandle.h" #include "eccodes.h" using namespace std; namespace metkit { namespace grib { GribIterator::GribIterator(const GribHandle& handle) : iterator_(nullptr) { int ret = 0; iterator_ = grib_iterator_new(handle.raw(), 0, &ret); ASSERT(iterator_); CODES_CALL(ret); } GribIterator::~GribIterator() noexcept(false) { if (iterator_) { CODES_CALL(grib_iterator_delete(iterator_)); iterator_ = 0; } } bool GribIterator::next(double& lat, double& lon, double& value) { return grib_iterator_next(iterator_, &lat, &lon, &value); } } // namespace grib } // namespace metkit metkit-1.16.0/src/metkit/codes/GribIterator.h000066400000000000000000000022441513171467200210340ustar00rootroot00000000000000/* * (C) Copyright 1996- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ #pragma once #include "eckit/filesystem/PathName.h" #include "eckit/io/Buffer.h" #include "eckit/log/CodeLocation.h" #include "eckit/memory/NonCopyable.h" struct grib_iterator; namespace eckit { class DataHandle; } namespace metkit { namespace grib { //---------------------------------------------------------------------------------------------------------------------- class GribHandle; class GribIterator : private eckit::NonCopyable { public: GribIterator(const GribHandle&); ~GribIterator() noexcept(false); bool next(double& lat, double& lon, double& value); private: // members grib_iterator* iterator_; }; //------------------------------------------------------------------------------------------------------ } // namespace grib } // namespace metkit metkit-1.16.0/src/metkit/codes/LibEccodes.cc000066400000000000000000000023711513171467200205720ustar00rootroot00000000000000/* * (C) Copyright 1996- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ /// @author Olivier Iffrig /// @date October 2019 #include "eccodes.h" #include "metkit/codes/LibEccodes.h" namespace metkit { //---------------------------------------------------------------------------------------------------------------------- REGISTER_LIBRARY(LibEccodes); LibEccodes::LibEccodes() : Library("eccodes") {} const LibEccodes& LibEccodes::instance() { static LibEccodes libeccodes; return libeccodes; } std::string LibEccodes::version() const { return ECCODES_VERSION_STR; } std::string LibEccodes::gitsha1(unsigned int count) const { std::string sha1(codes_get_git_sha1()); if (sha1.empty()) { return "not available"; } return sha1.substr(0, std::min(count, 40u)); } //---------------------------------------------------------------------------------------------------------------------- } // namespace metkit metkit-1.16.0/src/metkit/codes/LibEccodes.h000066400000000000000000000017761513171467200204440ustar00rootroot00000000000000/* * (C) Copyright 1996- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ /// @author Olivier Iffrig /// @date October 2019 #pragma once #include "eckit/system/Library.h" namespace metkit { //---------------------------------------------------------------------------------------------------------------------- class LibEccodes : public eckit::system::Library { public: LibEccodes(); static const LibEccodes& instance(); protected: std::string version() const override; std::string gitsha1(unsigned int count) const override; }; //---------------------------------------------------------------------------------------------------------------------- } // namespace metkit metkit-1.16.0/src/metkit/codes/MallocCodesContent.cc000066400000000000000000000026021513171467200223130ustar00rootroot00000000000000/* * (C) Copyright 2017- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ /// @author Baudouin Raoult /// @date Jun 2020 #include #include #include "eckit/exception/Exceptions.h" #include "eckit/message/MessageContent.h" #include "metkit/codes/CodesContent.h" #include "metkit/codes/MallocCodesContent.h" #include "eccodes.h" /// @todo remove this depedency on eccodes fom here namespace metkit { namespace codes { MallocCodesContent::MallocCodesContent(void* data, size_t size, const eckit::Offset& offset) : CodesContent(codes_handle_new_from_message(nullptr, data, size), true), buffer_(data), length_(size), offset_(offset) {} MallocCodesContent::~MallocCodesContent() { ::free(buffer_); } void MallocCodesContent::print(std::ostream& s) const { s << "MallocCodesContent[]"; } eckit::Offset MallocCodesContent::offset() const { return offset_; } const void* MallocCodesContent::data() const { return buffer_; } size_t MallocCodesContent::length() const { return length_; } } // namespace codes } // namespace metkit metkit-1.16.0/src/metkit/codes/MallocCodesContent.h000066400000000000000000000020731513171467200221570ustar00rootroot00000000000000/* * (C) Copyright 2017- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ /// @author Baudouin Raoult /// @author Tiago Quintino /// @date Jun 2020 #pragma once #include "eckit/io/Offset.h" #include "metkit/codes/CodesContent.h" namespace metkit { namespace codes { class MallocCodesContent : public CodesContent { public: MallocCodesContent(void* data, size_t size, const eckit::Offset& offset); ~MallocCodesContent(); private: // methods void print(std::ostream& s) const override; eckit::Offset offset() const override; const void* data() const override; size_t length() const override; private: // members void* buffer_; size_t length_; eckit::Offset offset_; }; } // namespace codes } // namespace metkit metkit-1.16.0/src/metkit/codes/api/000077500000000000000000000000001513171467200170355ustar00rootroot00000000000000metkit-1.16.0/src/metkit/codes/api/CodesAPI.cc000066400000000000000000000603601513171467200207400ustar00rootroot00000000000000/* * (C) Copyright 2025- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ #include "metkit/codes/api/CodesAPI.h" #include "metkit/codes/api/CodesTypes.h" #include "eckit/log/CodeLocation.h" #include "eccodes.h" namespace std { template <> struct default_delete { void operator()(codes_handle* h) { ::codes_handle_delete(h); } }; template <> struct default_delete { void operator()(codes_keys_iterator* it) { ::codes_keys_iterator_delete(it); } }; template <> struct default_delete { void operator()(codes_iterator* it) { ::codes_grib_iterator_delete(it); } }; } // namespace std namespace metkit::codes { namespace { void throwOnError(int code, const eckit::CodeLocation& l, const char* details) { if (code != 0) { std::string msg = std::string(details) + std::string(": ") + std::string(codes_get_error_message(code)); throw CodesException(msg, l); } }; void throwOnError(int code, const eckit::CodeLocation& l, const char* details, const std::string& key) { if (code != 0) { std::string msg = std::string(details) + std::string(": ") + std::string(codes_get_error_message(code)) + std::string(" for key ") + key; throw CodesException(msg, l); } }; /// Concrete implementation of CodesHandle. /// OwningCodesHandle is a owning container around a codes_handle* that /// makes the C APi accessible to C++ for any codes_handle*. /// It will properly delete the underlying codes_handle* on /// construction. class OwningCodesHandle : public CodesHandle { public: OwningCodesHandle(std::unique_ptr handle) : handle_{std::move(handle)} {}; virtual ~OwningCodesHandle() {}; OwningCodesHandle(OwningCodesHandle&&) = default; OwningCodesHandle& operator=(OwningCodesHandle&&) = default; size_t messageSize() const override; bool isDefined(const std::string& key) const override; bool isMissing(const std::string& key) const override; bool has(const std::string& key) const override; void setMissing(const std::string& key) override; void set(const std::string& key, const std::string& value) override; void set(const std::string& key, double value) override; void set(const std::string& key, long value) override; void set(const std::string& key, Span value) override; void set(const std::string& key, Span value) override; void set(const std::string& key, Span value) override; void set(const std::string& key, Span value) override; void set(const std::string& key, Span value) override; void set(const std::string& key, Span value) override; void forceSet(const std::string& key, Span value) override; void forceSet(const std::string& key, Span value) override; size_t size(const std::string& key) const override; CodesValue get(const std::string& key) const override; NativeType type(const std::string& key) const override; long getLong(const std::string& key) const override; double getDouble(const std::string& key) const override; std::string getString(const std::string& key) const override; std::vector getLongArray(const std::string& key) const override; std::vector getDoubleArray(const std::string& key) const override; std::vector getFloatArray(const std::string& key) const override; std::vector getStringArray(const std::string& key) const override; std::vector getBytes(const std::string& key) const override; /// Clones the underyling handle. /// Uses `codes_handle_clone` internally. /// @return Unique pointer to a cloned `CodesHandle` instance. std::unique_ptr clone() const override; /// Copy the message into a new allocated buffer /// @param data Pointer to an allocated array /// @param size Size of the allocated array void copyInto(uint8_t* data, size_t size) const override; KeyRange keys(KeyIteratorFlags flags = KeyIteratorFlags::AllKeys, std::optional ns = std::optional{}) const override; KeyRange keys(Namespace ns) const override; GeoRange values() const override; /// Release the raw `codes_handle*` - used to pass ownership out of C++ (e.g. python) void* release() override { return handle_.release(); }; protected: codes_handle* raw() const { if (!handle_) { throw CodesException("CodesHandle has been released.", Here()); } return handle_.get(); } private: std::unique_ptr handle_; }; size_t OwningCodesHandle::messageSize() const { size_t size; throwOnError(codes_get_message_size(raw(), &size), Here(), "CodesHandle::messageSize()"); return size; } bool OwningCodesHandle::isDefined(const std::string& key) const { return codes_is_defined(raw(), key.c_str()) == 1; } bool OwningCodesHandle::isMissing(const std::string& key) const { int err = 0; bool res = codes_is_missing(raw(), key.c_str(), &err) == 1; throwOnError(err, Here(), "CodesHandle::isMissing()", key); return res; } bool OwningCodesHandle::has(const std::string& key) const { return isDefined(key) && !isMissing(key); } /// Set a key to its missing value void OwningCodesHandle::setMissing(const std::string& key) { throwOnError(codes_set_missing(raw(), key.c_str()), Here(), "CodesHandle::setMissing()", key); } void OwningCodesHandle::set(const std::string& key, const std::string& value) { size_t size = value.size(); throwOnError(codes_set_string(raw(), key.c_str(), value.c_str(), &size), Here(), "CodesHandle::set(string, string)", key); } void OwningCodesHandle::set(const std::string& key, double value) { throwOnError(codes_set_double(raw(), key.c_str(), value), Here(), "CodesHandle::set(string, double)", key); } void OwningCodesHandle::set(const std::string& key, long value) { throwOnError(codes_set_long(raw(), key.c_str(), value), Here(), "CodesHandle::set(string, long)", key); } /// Set arrays void OwningCodesHandle::set(const std::string& key, Span value) { std::vector out; out.reserve(value.size()); for (auto it = value.data(); it != value.data() + value.size(); ++it) { out.push_back(it->c_str()); } set(key, out); } void OwningCodesHandle::set(const std::string& key, Span value) { throwOnError(codes_set_string_array(raw(), key.c_str(), const_cast(value.data()), value.size()), Here(), "CodesHandle::set(string, span)", key); } /// set string array void OwningCodesHandle::set(const std::string& key, Span value) { throwOnError(codes_set_double_array(raw(), key.c_str(), value.data(), value.size()), Here(), "CodesHandle::set(string, span)", key); } void OwningCodesHandle::set(const std::string& key, Span value) { throwOnError(codes_set_float_array(raw(), key.c_str(), value.data(), value.size()), Here(), "CodesHandle::set(string, span)", key); } void OwningCodesHandle::set(const std::string& key, Span value) { throwOnError(codes_set_long_array(raw(), key.c_str(), value.data(), value.size()), Here(), "CodesHandle::set(string, span)", key); } void OwningCodesHandle::set(const std::string& key, Span value) { size_t size = value.size(); throwOnError(codes_set_bytes(raw(), key.c_str(), value.data(), &size), Here(), "CodesHandle::set(string, span)", key); } void OwningCodesHandle::forceSet(const std::string& key, Span value) { throwOnError(codes_set_force_double_array(raw(), key.c_str(), value.data(), value.size()), Here(), "CodesHandle::forceSet(string, span)", key); } void OwningCodesHandle::forceSet(const std::string& key, Span value) { throwOnError(codes_set_force_float_array(raw(), key.c_str(), value.data(), value.size()), Here(), "CodesHandle::forceSet(string, span)", key); } size_t OwningCodesHandle::size(const std::string& key) const { size_t size; throwOnError(codes_get_size(raw(), key.c_str(), &size), Here(), "CodesHandle::size(string)", key); return size; } /// Get the value of the key CodesValue OwningCodesHandle::get(const std::string& key) const { NativeType ktype = type(key); bool isArray = size(key) > 1; switch (ktype) { case NativeType::Long: if (isArray) { return getLongArray(key); } else { return getLong(key); } case NativeType::Double: if (isArray) { return getDoubleArray(key); } else { return getDouble(key); } case NativeType::String: if (isArray) { return getStringArray(key); } else { return getString(key); } case NativeType::Bytes: return getBytes(key); case NativeType::Undefined: throw CodesException(std::string("CodesHandle::get(") + key + std::string("): Native type is UNDEFINED"), Here()); case NativeType::Section: case NativeType::Label: case NativeType::Missing: default: return getString(key); } } /// Get the type of the key NativeType OwningCodesHandle::type(const std::string& key) const { int type; throwOnError(codes_get_native_type(raw(), key.c_str(), &type), Here(), "CodesHandle::type(string)", key); switch (type) { case CODES_TYPE_LONG: return NativeType::Long; case CODES_TYPE_DOUBLE: return NativeType::Double; case CODES_TYPE_STRING: return NativeType::String; case CODES_TYPE_BYTES: return NativeType::Bytes; case CODES_TYPE_SECTION: return NativeType::Section; case CODES_TYPE_LABEL: return NativeType::Label; case CODES_TYPE_MISSING: return NativeType::Missing; default: return NativeType::Undefined; } } /// Explicit getters long OwningCodesHandle::getLong(const std::string& key) const { long value; throwOnError(codes_get_long(raw(), key.c_str(), &value), Here(), "CodesHandle::getLong(string)", key); return value; } double OwningCodesHandle::getDouble(const std::string& key) const { double value; throwOnError(codes_get_double(raw(), key.c_str(), &value), Here(), "CodesHandle::getDouble(string)", key); return value; } std::string OwningCodesHandle::getString(const std::string& key) const { std::string ret; std::size_t keylen = 1024; ret.resize(keylen); throwOnError(codes_get_string(raw(), key.c_str(), ret.data(), &keylen), Here(), "CodesHandle::getString(string)", key); ret.resize(strlen(ret.c_str())); return ret; } std::vector OwningCodesHandle::getLongArray(const std::string& key) const { std::vector ret; std::size_t ksize = size(key); ret.resize(ksize); throwOnError(codes_get_long_array(raw(), key.c_str(), ret.data(), &ksize), Here(), "CodesHandle::getLongArray(string)", key); ret.resize(ksize); return ret; } std::vector OwningCodesHandle::getDoubleArray(const std::string& key) const { std::vector ret; std::size_t ksize = size(key); ret.resize(ksize); throwOnError(codes_get_double_array(raw(), key.c_str(), ret.data(), &ksize), Here(), "CodesHandle::getDoubleArray(string)", key); ret.resize(ksize); return ret; } std::vector OwningCodesHandle::getFloatArray(const std::string& key) const { std::vector ret; std::size_t ksize = size(key); ret.resize(ksize); throwOnError(codes_get_float_array(raw(), key.c_str(), ret.data(), &ksize), Here(), "CodesHandle::getFloatArray(string)", key); ret.resize(ksize); return ret; } std::vector OwningCodesHandle::getStringArray(const std::string& key) const { std::vector cstrings; std::size_t ksize = size(key); cstrings.resize(ksize); throwOnError(codes_get_string_array(raw(), key.c_str(), cstrings.data(), &ksize), Here(), "CodesHandle::getStringArray(string)", key); cstrings.resize(ksize); std::vector ret; ret.reserve(cstrings.size()); for (char* cstr : cstrings) { ret.push_back(cstr); } return ret; } std::vector OwningCodesHandle::getBytes(const std::string& key) const { std::vector ret; std::size_t ksize = size(key); ret.resize(ksize); throwOnError(codes_get_bytes(raw(), key.c_str(), ret.data(), &ksize), Here(), "CodesHandle::getBytes(string)", key); ret.resize(ksize); return ret; } /// Cloning the whole handle. Expected to be wrapped by the user explicitly std::unique_ptr OwningCodesHandle::clone() const { std::unique_ptr ret{codes_handle_clone(raw())}; if (!ret) { throw CodesException("CodesHandle::clone() failed", Here()); } return std::make_unique(std::move(ret)); } /// Copy the message into a new allocated buffer void OwningCodesHandle::copyInto(uint8_t* data, size_t size) const { std::size_t s = size; throwOnError(codes_get_message_copy(raw(), data, &s), Here(), "CodesHandle::copy(uint8_t*, size_t*)"); } class ConcreteKeyIterator : public KeyIterator { public: // methods ConcreteKeyIterator(const OwningCodesHandle& handle, std::unique_ptr it) : refHandle_{std::cref(handle)}, it_{std::move(it)}, isValid_{false} { next(); } virtual ~ConcreteKeyIterator() {} std::string name() const override { return codes_keys_iterator_get_name(it_.get()); }; /// Get the value of the key CodesValue get() const override { std::string key = name(); NativeType type = refHandle_.get().type(key); bool isArray = refHandle_.get().size(key) > 1; switch (type) { case NativeType::Long: if (isArray) { return getLongArray(); } else { return getLong(); } case NativeType::Double: if (isArray) { return getDoubleArray(); } else { return getDouble(); } case NativeType::String: if (isArray) { return getStringArray(); } else { return getString(); } case NativeType::Bytes: return getBytes(); case NativeType::Undefined: throw CodesException(std::string("IteratedKey::get(") + key + std::string("): Native type is UNDEFINED")); case NativeType::Section: case NativeType::Label: case NativeType::Missing: default: return getString(); } }; /// Get the type of the key NativeType type() const override { return refHandle_.get().type(name()); }; /// Explicit getters long getLong() const override { long value; size_t size = 1; throwOnError(codes_keys_iterator_get_long(it_.get(), &value, &size), Here(), "KeyIterator::getLong()"); return value; } double getDouble() const override { double value; size_t size = 1; throwOnError(codes_keys_iterator_get_double(it_.get(), &value, &size), Here(), "KeyIterator::getDouble()"); return value; } float getFloat() const override { float value; size_t size = 1; throwOnError(codes_keys_iterator_get_float(it_.get(), &value, &size), Here(), "KeyIterator::getFloat()"); return value; } std::string getString() const override { std::string ret; std::size_t keylen = 1024; ret.resize(keylen); throwOnError(codes_keys_iterator_get_string(it_.get(), ret.data(), &keylen), Here(), "KeyIterator::getString()"); ret.resize(strlen(ret.c_str())); return ret; } std::vector getLongArray() const override { std::vector ret; std::string key = name(); std::size_t size = refHandle_.get().size(key); ret.resize(size); throwOnError(codes_keys_iterator_get_long(it_.get(), ret.data(), &size), Here(), "KeyIterator::getLongArray()"); ret.resize(size); return ret; } std::vector getDoubleArray() const override { std::vector ret; std::string key = name(); std::size_t size = refHandle_.get().size(key); ret.resize(size); throwOnError(codes_keys_iterator_get_double(it_.get(), ret.data(), &size), Here(), "KeyIterator::getDoubleArray"); ret.resize(size); return ret; } std::vector getFloatArray() const override { std::vector ret; std::string key = name(); std::size_t size = refHandle_.get().size(key); ret.resize(size); throwOnError(codes_keys_iterator_get_float(it_.get(), ret.data(), &size), Here(), "KeyIterator::getFloatArray"); ret.resize(size); return ret; } std::vector getStringArray() const override { // There is no other option to get string array return refHandle_.get().getStringArray(name()); } std::vector getBytes() const override { std::vector ret; std::string key = name(); std::size_t size = refHandle_.get().size(key); ret.resize(size); throwOnError(codes_keys_iterator_get_bytes(it_.get(), ret.data(), &size), Here(), "KeyIterator::getBytes()"); ret.resize(size); return ret; } protected: void next() override { isValid_ = codes_keys_iterator_next(it_.get()) > 0; } bool isValid() const override { return isValid_; } private: std::reference_wrapper refHandle_; std::unique_ptr it_; bool isValid_; }; unsigned long mapFlags(KeyIteratorFlags flags) { unsigned long res = 0; if (hasFlag(flags, KeyIteratorFlags::AllKeys)) { res |= CODES_KEYS_ITERATOR_ALL_KEYS; } if (hasFlag(flags, KeyIteratorFlags::SkipReadOnly)) { res |= CODES_KEYS_ITERATOR_SKIP_READ_ONLY; } if (hasFlag(flags, KeyIteratorFlags::SkipOptional)) { res |= CODES_KEYS_ITERATOR_SKIP_OPTIONAL; } if (hasFlag(flags, KeyIteratorFlags::SkipEditionSpecific)) { res |= CODES_KEYS_ITERATOR_SKIP_EDITION_SPECIFIC; } if (hasFlag(flags, KeyIteratorFlags::SkipCoded)) { res |= CODES_KEYS_ITERATOR_SKIP_CODED; } if (hasFlag(flags, KeyIteratorFlags::SkipComputed)) { res |= CODES_KEYS_ITERATOR_SKIP_COMPUTED; } if (hasFlag(flags, KeyIteratorFlags::SkipDuplicates)) { res |= CODES_KEYS_ITERATOR_SKIP_DUPLICATES; } if (hasFlag(flags, KeyIteratorFlags::SkipFunction)) { res |= CODES_KEYS_ITERATOR_SKIP_FUNCTION; } return res; } /// Iterate keys on an iterator with a range based for loop KeyRange OwningCodesHandle::keys(KeyIteratorFlags flags, std::optional ns) const { return KeyRange{ std::make_unique(*this, std::unique_ptr(codes_keys_iterator_new( raw(), mapFlags(flags), ns ? ns->c_str() : NULL)))}; }; KeyRange OwningCodesHandle::keys(Namespace ns) const { return keys(KeyIteratorFlags::AllKeys, ns); }; class ConcreteIteratedGeoData : public GeoIterator { public: // methods ConcreteIteratedGeoData(const OwningCodesHandle& handle, std::unique_ptr it) : refHandle_{std::ref(handle)}, it_{std::move(it)}, data_{0.0, 0.0, 0.0}, isValid_{false} { if (hasNext()) { next(); } } virtual ~ConcreteIteratedGeoData() {} /// Returns the name of the key const GeoData& data() const override { return data_; }; bool hasNext() const override { return codes_grib_iterator_has_next(it_.get()) > 0; }; protected: void next() override { isValid_ = codes_grib_iterator_next(it_.get(), &data_.latitude, &data_.longitude, &data_.value) > 0; } bool isValid() const override { return isValid_; } private: std::reference_wrapper refHandle_; std::unique_ptr it_; GeoData data_; bool isValid_; }; /// Iterate OwningCodesHandle::values with longitude and latituted GeoRange OwningCodesHandle::values() const { int err; GeoRange res{std::make_unique( *this, std::unique_ptr(codes_grib_iterator_new(raw(), 0, &err)))}; throwOnError(err, Here(), "CodesHandle::values()"); return res; }; } // namespace std::string samplesPath() { return codes_samples_path(NULL); } std::string definitionPath() { return codes_definition_path(NULL); } long apiVersion() { return codes_get_api_version(); } std::string gitSha1() { return codes_get_git_sha1(); } std::string gitBranch() { return codes_get_git_branch(); } std::string buildDate() { return codes_get_build_date(); } std::string packageName() { return codes_get_package_name(); } std::unique_ptr codesHandleFromMessage(Span data) { return std::make_unique(std::unique_ptr( codes_handle_new_from_message(NULL, static_cast(data.data()), data.size()))); } std::unique_ptr codesHandleFromMessageCopy(Span data) { return std::make_unique(std::unique_ptr( codes_handle_new_from_message_copy(NULL, static_cast(data.data()), data.size()))); } std::unique_ptr codesHandleFromSample(const std::string& sampleName, std::optional product) { if (product) { switch (*product) { case Product::GRIB: return std::make_unique( std::unique_ptr(codes_grib_handle_new_from_samples(NULL, sampleName.c_str()))); case Product::BUFR: return std::make_unique( std::unique_ptr(codes_bufr_handle_new_from_samples(NULL, sampleName.c_str()))); default: return std::make_unique( std::unique_ptr(codes_handle_new_from_samples(NULL, sampleName.c_str()))); } } return std::make_unique( std::unique_ptr(codes_handle_new_from_samples(NULL, sampleName.c_str()))); } std::unique_ptr codesHandleFromFile(const std::string& fpath, Product product) { int err = 0; std::unique_ptr ret; FILE* file = fopen(fpath.c_str(), "rb"); // "w" means write mode if (file == nullptr) { throw CodesException(std::string("Error opening file ") + fpath, Here()); } switch (product) { case Product::GRIB: ret = std::unique_ptr(codes_grib_handle_new_from_file(NULL, file, &err)); break; case Product::BUFR: ret = std::unique_ptr(codes_bufr_handle_new_from_file(NULL, file, &err)); break; }; fclose(file); throwOnError(err, Here(), "codesHandleFromFile(FILE*, Product): "); if (!ret) { throw CodesException("codes_handle_new_from_file returned NULL without an additional error"); } return std::make_unique(std::move(ret)); } } // namespace metkit::codes metkit-1.16.0/src/metkit/codes/api/CodesAPI.h000066400000000000000000000406541513171467200206060ustar00rootroot00000000000000/* * (C) Copyright 2025- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ #pragma once #include "metkit/codes/api/CodesTypes.h" #include "metkit/codes/api/GeoIterator.h" #include "metkit/codes/api/KeyIterator.h" #include #include #include #include #include /// This file contains the important parts for an eccodes c api wrapper. /// It does not wrap the whole `eccodes.h`. /// The most important interface is the `CodesHandle` - it use to work on specific GRIB or BUFR messages. /// An addition to that, a few factory functions (`codesHandleFromMessage`, `codesHandleFromSample`, /// `codesHandleFromFile`) and iterators are wrapped. /// /// Missing components: /// * codes_context /// * codes_index /// * codes_fieldset /// * codes_values /// * multio_handle /// * codes_nearest /// * GTS handling /// * GRIBEX namespace metkit::codes { //---------------------------------------------------------------------------------------------------------------------- /// Retrieve information about the configured samples path. /// @return The configured path to sample files. std::string samplesPath(); /// Retrieve information about the configured definition path. /// @return The configured path to the definition files. std::string definitionPath(); /// Retrieve eccodes version /// @return The eccodes version. long apiVersion(); /// Retrieve repository information of the built. /// @return The SHA1 of the latest commit the eccodes library has been built on. std::string gitSha1(); /// Retrieve repository information of the built. /// @return The branch the eccodes library has been built on. std::string gitBranch(); /// Retrieve repository information of the built. /// @return The built date of the eccodes library. std::string buildDate(); /// Retrieve repository information of the built. /// @return The package name the library has been distributed with. std::string packageName(); //---------------------------------------------------------------------------------------------------------------------- /// Abstract interface wrapping eccodes handles. /// /// Eccodes exposed `codes_handle*` is used to handle GRIB1, GRIB2 and BUFR data. class CodesHandle { friend class KeyRange; friend class GeoRange; public: virtual ~CodesHandle() = default; /// Retrieve binary size of the handled message. /// @return Size of the message in bytes. virtual size_t messageSize() const = 0; /// Check if a key is defined. /// @param key Name of the field that is checked to be defined. /// @return True if the field is defined. virtual bool isDefined(const std::string& key) const = 0; /// Check if a key is missing. /// @param key Name of the field that is checked to be missing. /// @return True if the field is missing. virtual bool isMissing(const std::string& key) const = 0; /// Check if a key is defined and not missing. /// @param key Name of the field that is checked to exist and have a value. /// @return True if the field exists and has a value. virtual bool has(const std::string& key) const = 0; /// Set a key to its missing value. /// @param key Name of the field that is supposed to be set to its missing value. virtual void setMissing(const std::string& key) = 0; /// Set scalar string value for a specific field. /// @param key Name of the field that is supposed to be set. /// @param value Value the field is supposed to be set to. virtual void set(const std::string& key, const std::string& value) = 0; /// Set scalar double value for a specific field. /// @param key Name of the field that is supposed to be set. /// @param value Value the field is supposed to be set to. virtual void set(const std::string& key, double value) = 0; /// Set scalar long value for a specific field. /// @param key Name of the field that is supposed to be set. /// @param value Value the field is supposed to be set to. virtual void set(const std::string& key, long value) = 0; /// Set scalar floating point value for a specific field. /// /// Overload for other floating point types. /// @param key Name of the field that is supposed to be set. /// @param value Value the field is supposed to be set to. template && std::is_floating_point_v, bool> = true> void set(const std::string& key, const T& v) { set(key, static_cast(v)); } /// Set scalar integral value for a specific field. /// /// Overload for other integral types. /// @param key Name of the field that is supposed to be set. /// @param value Value the field is supposed to be set on. template && std::is_integral_v, bool> = true> void set(const std::string& key, const T& v) { set(key, static_cast(v)); } /// Set array of string through `span` as general contiguous memory container. /// @param key Name of the field that is supposed to be set. /// @param value Contiguous array the field is supposed to be set to. virtual void set(const std::string& key, Span value) = 0; /// Set array of c-string through `span` as general contiguous memory container. /// @param key Name of the field that is supposed to be set. /// @param value Contiguous array the field is supposed to be set to. virtual void set(const std::string& key, Span value) = 0; /// Set array of double through `span` as general contiguous memory container. /// @param key Name of the field that is supposed to be set. /// @param value Contiguous array the field is supposed to be set to. virtual void set(const std::string& key, Span value) = 0; /// Set array of float through `span` as general contiguous memory container. /// @param key Name of the field that is supposed to be set. /// @param value Contiguous array the field is supposed to be set to. virtual void set(const std::string& key, Span value) = 0; /// Set array of long through `span` as general contiguous memory container. /// @param key Name of the field that is supposed to be set. /// @param value Contiguous array the field is supposed to be set to. virtual void set(const std::string& key, Span value) = 0; /// Set array of uint8_t (bytes) through `span` as general contiguous memory container. /// @param key Name of the field that is supposed to be set. /// @param value Contiguous array the field is supposed to be set to. virtual void set(const std::string& key, Span value) = 0; /// Set any type of value as sum type for a specific field. /// Visits the value and calls the corresponding `set` overload. /// A template and SFINAE is used to match exactly the type `CodesValue`, /// this avoids abiguous overloads through implict convertion. /// @param key Name of the field that is supposed to be set. /// @param value Value the field is supposed to be set to. template , bool> = true> void set(const std::string& key, const T& value) { std::visit([&](const auto& v) { this->set(key, v); }, value); } /// Force setting arrays of double through `span` as general contiguous memory container. /// /// Allows setting arrays that usually get computed through other keys /// @param key Name of the field that is supposed to be set to a specific value. /// @param value Value the field is supposed to be set on. virtual void forceSet(const std::string& key, Span value) = 0; /// Force setting arrays of float through `span` as general contiguous memory container /// /// Allows setting arrays that usually get computed through other keys /// @param key Name of the field that is supposed to be set to a specific value. /// @param value Value the field is supposed to be set on. virtual void forceSet(const std::string& key, Span value) = 0; /// Returns the number of elements contained for a given key /// /// Can be used to determine if a field is storing a scalar or an array. /// @param key Name of the field that is supposed to be inspected. /// @return For given scalars 1 is returned. For given arrays the size of the array is returned.. virtual size_t size(const std::string& key) const = 0; /// Get the value of the key. /// /// High-level functionality: /// Inspection on the contained valued is performed with `type` and `size`. /// Then the more specific `getXXX` call is performed. /// @param key Name of the field that is supposed to be retrieved. /// @return Variant of all possible value types. virtual CodesValue get(const std::string& key) const = 0; /// Get the type of the key /// @param key Name of the field that is supposed to be inspected. /// @return Enum of the native types ECCODES exposes. virtual NativeType type(const std::string& key) const = 0; /// Get the contained value for a key as long. /// @param key Name of the field that is supposed to be retrieved. /// @return Retrieved value contained for the passed key. virtual long getLong(const std::string& key) const = 0; /// Get the contained value for a key as double. /// @param key Name of the field that is supposed to be retrieved. /// @return Retrieved value contained for the passed key. virtual double getDouble(const std::string& key) const = 0; /// Get the contained value for a key as string. /// /// This should be possible for all key types. /// @param key Name of the field that is supposed to be retrieved. /// @return Retrieved value contained for the passed key. virtual std::string getString(const std::string& key) const = 0; /// Get the contained values for a key as array of long. /// @param key Name of the field that is supposed to be retrieved. /// @return Retrieved values contained for the passed key. virtual std::vector getLongArray(const std::string& key) const = 0; /// Get the contained values for a key as array of double. /// @param key Name of the field that is supposed to be retrieved. /// @return Retrieved values contained for the passed key. virtual std::vector getDoubleArray(const std::string& key) const = 0; /// Get the contained values for a key as array of float. /// @param key Name of the field that is supposed to be retrieved. /// @return Retrieved values contained for the passed key. virtual std::vector getFloatArray(const std::string& key) const = 0; /// Get the contained values for a key as array of string. /// /// This should be possible for all key types. /// @param key Name of the field that is supposed to be retrieved. /// @return Retrieved values contained for the passed key. virtual std::vector getStringArray(const std::string& key) const = 0; /// Get the contained values for a key as array of uint8_t (bytes). /// @param key Name of the field that is supposed to be retrieved. /// @return Retrieved values contained for the passed key. virtual std::vector getBytes(const std::string& key) const = 0; /// Clones the underyling handle. /// Uses `codes_handle_clone` internally. /// @return Unique pointer to a cloned `CodesHandle` instance. virtual std::unique_ptr clone() const = 0; /// Copy the message into a new allocated buffer /// @param data Pointer to an allocated array /// @param size Size of the allocated array. /// Should be containing at least the size returned by `messageSize`. virtual void copyInto(uint8_t* data, size_t size) const = 0; /// Iterate keys in a GRIB2 or BUFR handle. /// /// @param flags Iterator flags to filter keys /// @param ns A specific namespace that is iterated (e.g. "mars" or "ls"). /// Namespaces are defined within definition files, /// that means custom namespaces can be provided by users. /// Common namespaces that are available by the default definition files /// are listed in the namespace `codes::namespaces` /// @return A Range that can be iterated on with a range-based for-loop. /// @see KeyIterator virtual KeyRange keys(KeyIteratorFlags flags = KeyIteratorFlags::AllKeys, std::optional ns = std::optional{}) const = 0; /// Iterate keys in a GRIB2 or BUFR handle. /// /// @param ns A specific namespace that is iterated (e.g. "mars" or "ls"). /// Namespaces are defined within definition files, /// that means custom namespaces can be provided by users. /// Common namespaces that are available by the default definition files /// are listed in the namespace `codes::namespaces` /// @return A Range that can be iterated on with a range-based for-loop. /// @see KeyIterator virtual KeyRange keys(Namespace ns) const = 0; /// Iterate values with longitude and latituted. /// /// @return A Range that can be iterated on with a range-based for-loop. /// The iterated value contains a type `GeoData` /// with members `longitude`, `latitude` and `value`. /// @see GeoIterator virtual GeoRange values() const = 0; /// Release the underlying `codes_handle*`. /// /// After calling `release` the instance of this type is in an inoperable state. /// Used to pass ownership out of C++ (e.g. python). /// /// Example use: /// ```cpp /// auto rawHandle = reinterpret_cast(handl->release()); /// ``` /// /// @return Pointer to `codes_handle*` [[nodiscard]] virtual void* release() = 0; }; /// Create a new `CodesHandle` from a byte array. /// /// ECCODES does not copy the array until a modification is made. /// The user needs to maintain the lifetime of the passed array. /// @param data Array to an contiguous array of bytes. /// Lifetime of the array need to be maintained till the first change is made on the handle. /// @return Instance of a `CodesHandle` wrapped in a `unique_ptr`. /// @see codesHandleFromMessageCopy std::unique_ptr codesHandleFromMessage(Span data); /// Create a new `CodesHandle` from a byte array. /// /// ECCODES copies the array. No lifetime requirements exist on `data`. /// @param data Array to an contiguous array of bytes the message is created from. /// @return Instance of a `CodesHandle` wrapped in a `unique_ptr`. /// @see codesHandleFromMessage std::unique_ptr codesHandleFromMessageCopy(Span data); /// Create a new `CodesHandle` from a sample existing in the configured samples path. /// /// ECCODES does not copy the array until a modification is made. /// The user needs to maintain the lifetime of the passed array. /// @param sample Name of the sample in the sample path. Usually without the ".tmpl" suffix, e.g. "GRIB2". /// @param product The intented type of handle that is supposed to be loaded (BUFR or GRIB). /// Does not need to be specified. /// @return Instance of a `CodesHandle` wrapped in a `unique_ptr`. /// @see samplesPath std::unique_ptr codesHandleFromSample(const std::string& sampleName, std::optional product = std::optional{}); /// Create a new `CodesHandle` from a file. /// /// ECCODES does not copy the array until a modification is made. /// The user needs to maintain the lifetime of the passed array. /// @param file Pointer to a implementation dependent file handle containing a BUFR or GRIB message. /// @param product The intented type of handle that is supposed to be loaded (BUFR or GRIB). /// @return Instance of a `CodesHandle` wrapped in a `unique_ptr`. std::unique_ptr codesHandleFromFile(const std::string& fpath, Product); //---------------------------------------------------------------------------------------------------------------------- } // namespace metkit::codes metkit-1.16.0/src/metkit/codes/api/CodesTypes.cc000066400000000000000000000012151513171467200214250ustar00rootroot00000000000000/* * (C) Copyright 2025- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ #include "metkit/codes/api/CodesTypes.h" namespace metkit::codes { CodesException::CodesException(const std::string& reason, const eckit::CodeLocation& l) : eckit::Exception(std::string("CodesException: ") + reason, l) {}; } // namespace metkit::codes metkit-1.16.0/src/metkit/codes/api/CodesTypes.h000066400000000000000000000050521513171467200212720ustar00rootroot00000000000000/* * (C) Copyright 2025- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ #pragma once #include #include #include #include #include #include "eckit/exception/Exceptions.h" namespace metkit::codes { /// Exception that is thrown by the API to wrap eccodes errors class CodesException : public eckit::Exception { public: CodesException(const std::string& reason, const eckit::CodeLocation& l = eckit::CodeLocation()); }; /// Enum to classify types of handles enum class Product { GRIB, BUFR, }; /// Enum that redefines eccodes specific key types enum class NativeType { Undefined, Long, Double, String, Bytes, Section, Label, Missing, }; /// Sum type of possible values returned by eccodes. using CodesValue = std::variant, std::vector, std::vector, std::vector, std::vector>; //---------------------------------------------------------------------------------------------------------------------- /// To be replaced with std::span in C++20. template struct Span { using element_type = T; using value_type = std::remove_cv_t; const value_type* data_ = nullptr; std::size_t size_ = 0; const value_type* data() { return data_; } std::size_t size() { return size_; } Span() = default; Span(const T* p, std::size_t n) : data_(p), size_(n) {} // from std::vector template Span(const std::vector& v) : data_(v.data()), size_(v.size()) {} // from std::array template Span(const std::array& arr) : data_(arr.data()), size_(N) {} // from C array template Span(const value_type (&arr)[N]) : data_(arr), size_(N) {} // from std::basic_string template ::value, bool> = true> Span(const std::basic_string& s) : data_(s.data()), size_(s.size()) {} }; //---------------------------------------------------------------------------------------------------------------------- } // namespace metkit::codes metkit-1.16.0/src/metkit/codes/api/GeoIterator.h000066400000000000000000000053011513171467200214310ustar00rootroot00000000000000/* * (C) Copyright 2025- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ #pragma once #include "metkit/codes/api/CodesTypes.h" #include #include #include #include #include namespace metkit::codes { //---------------------------------------------------------------------------------------------------------------------- class GeoRange; /// Aggregate that stores a value with lon/lat. struct GeoData { double value; double longitude; double latitude; }; /// Abstract interface wrapping C API calls on on key_iterator. class GeoIterator { friend class GeoRange; public: virtual ~GeoIterator() = default; /// Access to the iterated data. /// @return Reference to the iterated geo data object. virtual const GeoData& data() const = 0; /// Check if there are follow up values. /// @return True if there are more values to iterate on. virtual bool hasNext() const = 0; protected: /// Iterates the next element. virtual void next() = 0; /// Check if the iterator is valid. /// @return True if the iterator is still valid and holds a value. False indicates end of iteration. virtual bool isValid() const = 0; }; //---------------------------------------------------------------------------------------------------------------------- /// Implements the geo iterator (codes_iterator) based on a C++ range. /// Enables use of range-based for-loop. class GeoRange { public: struct EndIterator; struct Iterator { friend struct EndIterator; Iterator& operator++() { state->next(); return *this; } const GeoData& operator*() const { return state->data(); } const GeoData* operator->() const { return &state->data(); } inline bool operator!=(const EndIterator&) { return state->isValid(); } GeoIterator* state; }; struct EndIterator { inline bool operator!=(const Iterator& it) { return it.state->isValid(); } }; Iterator begin() const { return Iterator{impl_.get()}; }; EndIterator end() const { return {}; } GeoRange(std::unique_ptr impl) : impl_{std::move(impl)} {}; private: std::unique_ptr impl_; }; //---------------------------------------------------------------------------------------------------------------------- } // namespace metkit::codes metkit-1.16.0/src/metkit/codes/api/KeyIterator.cc000066400000000000000000000034551513171467200216150ustar00rootroot00000000000000/* * (C) Copyright 2025- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ #include "metkit/codes/api/KeyIterator.h" #include "eccodes.h" namespace metkit::codes { KeyIteratorFlags operator|(KeyIteratorFlags a, KeyIteratorFlags b) { return static_cast(static_cast >(a) | static_cast >(b)); } KeyIteratorFlags operator&(KeyIteratorFlags a, KeyIteratorFlags b) { return static_cast(static_cast >(a) & static_cast >(b)); } KeyIteratorFlags operator^(KeyIteratorFlags a, KeyIteratorFlags b) { return static_cast(static_cast >(a) ^ static_cast >(b)); } KeyIteratorFlags operator~(KeyIteratorFlags a) { return static_cast(~static_cast >(a)); } bool hasFlag(KeyIteratorFlags value, KeyIteratorFlags flag) { return (static_cast >(value) & static_cast >(flag)) != 0; } //---------------------------------------------------------------------------------------------------------------------- } // namespace metkit::codes metkit-1.16.0/src/metkit/codes/api/KeyIterator.h000066400000000000000000000135341513171467200214560ustar00rootroot00000000000000/* * (C) Copyright 2025- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ #pragma once #include "metkit/codes/api/CodesTypes.h" #include #include #include namespace metkit::codes { /// A namepspace is defined through the definition files and represented as a string. using Namespace = std::string; /// Commonly used eccodes namespacess. namespace namespaces { /// LS namespace contains a collection of descriptive keys as used by `grib_ls`. const Namespace ls{"ls"}; const Namespace parameter{"parameter"}; const Namespace statistics{"statistics"}; const Namespace time{"time"}; const Namespace geography{"geography"}; const Namespace vertical{"vertical"}; /// MARS namespace contains keys used for indexation const Namespace mars{"mars"}; }; // namespace namespaces /// Flag to control/filter key iterator. /// /// Use `AllKeys` to disable filtering. /// Use combination of `Skip*` to filter. enum class KeyIteratorFlags : unsigned int { /// Default - Will iterate all keys in a namespace. AllKeys = 0, SkipReadOnly = 1 << 0, SkipOptional = 1 << 1, SkipEditionSpecific = 1 << 2, SkipCoded = 1 << 3, SkipComputed = 1 << 4, SkipDuplicates = 1 << 5, SkipFunction = 1 << 6, }; KeyIteratorFlags operator|(KeyIteratorFlags a, KeyIteratorFlags b); KeyIteratorFlags operator&(KeyIteratorFlags a, KeyIteratorFlags b); KeyIteratorFlags operator^(KeyIteratorFlags a, KeyIteratorFlags b); KeyIteratorFlags operator~(KeyIteratorFlags a); /// Optional helper to check if a flag is set. bool hasFlag(KeyIteratorFlags value, KeyIteratorFlags flag); //---------------------------------------------------------------------------------------------------------------------- class KeyRange; /// Abstract interface wrapping C API calls on on key_iterator. class KeyIterator { friend class KeyRange; public: virtual ~KeyIterator() = default; /// Get the name of the iterated key. /// @return Name of the iterated key. virtual std::string name() const = 0; /// Get the value of the key. /// /// High-level functionality: /// Inspection on the contained valued is performed with `type` and `size`. /// Then the more specific `getXXX` call is performed. /// @return Variant of all possible value types. virtual CodesValue get() const = 0; /// Get the type of the iterated key. /// @return Type of the iterated key. virtual NativeType type() const = 0; /// Get the contained value for a key as long. /// @return Retrieved value contained for the iterated key. virtual long getLong() const = 0; /// Get the contained value for a key as double. /// @return Retrieved value contained for the iterated key. virtual double getDouble() const = 0; /// Get the contained value for a key as float. /// @return Retrieved value contained for the iterated key. virtual float getFloat() const = 0; /// Get the contained value for a key as string. /// /// This should be possible for all key types. /// @return Retrieved value contained for the iterated key. virtual std::string getString() const = 0; /// Get the contained values for a key as array of long. /// @return Retrieved values contained for the iterated key. virtual std::vector getLongArray() const = 0; /// Get the contained values for a key as array of double. /// @return Retrieved values contained for the iterated key. virtual std::vector getDoubleArray() const = 0; /// Get the contained values for a key as array of float. /// @return Retrieved values contained for the iterated key. virtual std::vector getFloatArray() const = 0; /// Get the contained values for a key as array of string. /// @return Retrieved values contained for the iterated key. virtual std::vector getStringArray() const = 0; /// Get the contained values for a key as array of uint8_t (bytes). /// @return Retrieved values contained for the iterated key. virtual std::vector getBytes() const = 0; protected: /// Iterates the next element. virtual void next() = 0; /// Check if the iterator is valid. /// @return True if the iterator is still valid and holds a value. False indicates end of iteration. virtual bool isValid() const = 0; }; //---------------------------------------------------------------------------------------------------------------------- /// Implements the key iterator (codes_key_iterator) based on a C++ range. /// Enables use of range-based for-loop. class KeyRange { public: struct EndIterator; struct Iterator { friend struct EndIterator; Iterator& operator++() { state->next(); return *this; }; const KeyIterator& operator*() const { return *state; }; const KeyIterator* operator->() const { return state; }; inline bool operator!=(const KeyRange::EndIterator&) { return state->isValid(); } KeyIterator* state; }; struct EndIterator { inline bool operator!=(const KeyRange::Iterator& it) { return it.state->isValid(); } }; Iterator begin() const { return Iterator{impl_.get()}; }; EndIterator end() const { return {}; }; KeyRange(std::unique_ptr impl) : impl_{std::move(impl)} {}; private: std::unique_ptr impl_; }; //---------------------------------------------------------------------------------------------------------------------- } // namespace metkit::codes metkit-1.16.0/src/metkit/config/000077500000000000000000000000001513171467200164345ustar00rootroot00000000000000metkit-1.16.0/src/metkit/config/LibMetkit.cc000066400000000000000000000047361513171467200206410ustar00rootroot00000000000000/* * (C) Copyright 1996- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ /// @author Baudouin Raoult /// @author Tiago Quintino /// @date August 2016 #include "metkit/config/LibMetkit.h" #include #include "eckit/config/Resource.h" #include "metkit/metkit_version.h" namespace metkit { //---------------------------------------------------------------------------------------------------------------------- REGISTER_LIBRARY(LibMetkit); LibMetkit::LibMetkit() : Library("metkit") {} const LibMetkit& LibMetkit::instance() { static LibMetkit libmetkit; return libmetkit; } const void* LibMetkit::addr() const { return this; } std::string LibMetkit::version() const { return metkit_version_str(); } std::string LibMetkit::gitsha1(unsigned int count) const { std::string sha1(metkit_git_sha1()); if (sha1.empty()) { return "not available"; } return sha1.substr(0, std::min(count, 40u)); } eckit::PathName LibMetkit::configFile(const std::string& filename) { return eckit::PathName{"~metkit/share/metkit"} / filename; } eckit::PathName LibMetkit::languageYamlFile() { return LibMetkit::configFile("language.yaml"); } std::vector LibMetkit::modifiersYamlFiles() { return std::vector{LibMetkit::configFile("modifiers.yaml"), LibMetkit::configFile("reportype.yaml")}; } eckit::PathName LibMetkit::paramYamlFile() { return LibMetkit::configFile("params.yaml"); } eckit::PathName LibMetkit::paramStaticYamlFile() { return LibMetkit::configFile("params-static.yaml"); } eckit::PathName LibMetkit::shortnameContextYamlFile() { return LibMetkit::configFile("shortname-context.yaml"); } eckit::PathName LibMetkit::paramIDYamlFile() { return LibMetkit::configFile("paramids.yaml"); } eckit::PathName LibMetkit::paramMatchingYamlFile() { return LibMetkit::configFile("param-matching.yaml"); } eckit::PathName LibMetkit::bufrSubtypesYamlFile() { return LibMetkit::configFile("bufr-subtypes.yaml"); } } // namespace metkit //---------------------------------------------------------------------------------------------------------------------- metkit-1.16.0/src/metkit/config/LibMetkit.h000066400000000000000000000031421513171467200204710ustar00rootroot00000000000000/* * (C) Copyright 1996- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ /// @author Baudouin Raoult /// @author Tiago Quintino /// @date August 2016 #ifndef mir_LibMetkit_H #define mir_LibMetkit_H #include "eckit/filesystem/PathName.h" #include "eckit/system/Library.h" //---------------------------------------------------------------------------------------------------------------------- namespace metkit { class LibMetkit : public eckit::system::Library { public: LibMetkit(); static eckit::PathName configFile(const std::string& filename); static eckit::PathName languageYamlFile(); static std::vector modifiersYamlFiles(); static eckit::PathName paramYamlFile(); static eckit::PathName paramStaticYamlFile(); static eckit::PathName paramIDYamlFile(); static eckit::PathName paramMatchingYamlFile(); static eckit::PathName shortnameContextYamlFile(); static eckit::PathName bufrSubtypesYamlFile(); static const LibMetkit& instance(); protected: const void* addr() const; virtual std::string version() const; virtual std::string gitsha1(unsigned int count) const; }; } // namespace metkit //---------------------------------------------------------------------------------------------------------------------- #endif metkit-1.16.0/src/metkit/fields/000077500000000000000000000000001513171467200164355ustar00rootroot00000000000000metkit-1.16.0/src/metkit/fields/FieldIndex.cc000066400000000000000000000074121513171467200207630ustar00rootroot00000000000000/* * (C) Copyright 1996- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ #include #include "eckit/exception/Exceptions.h" #include "eckit/message/Message.h" #include "eckit/utils/StringTools.h" #include "metkit/fields/FieldIndex.h" namespace metkit { namespace fields { FieldIndex::FieldIndex() {} FieldIndex::FieldIndex(eckit::Stream& s) { bool b, more; std::string key; std::string str; long ival; double dval; s >> more; while (more) { s >> key; s >> b; if (b) { s >> str; stringValues_[key] = str; } s >> b; if (b) { s >> ival; longValues_[key] = ival; } s >> b; if (b) { s >> dval; doubleValues_[key] = dval; } s >> more; } } FieldIndex::FieldIndex(const eckit::message::Message& message) { eckit::message::TypedSetter gather(*this); message.getMetadata(gather); } void FieldIndex::encode(eckit::Stream& s) const { std::set keys; for (auto j = stringValues_.begin(); j != stringValues_.end(); ++j) { keys.insert((*j).first); } for (auto j = longValues_.begin(); j != longValues_.end(); ++j) { keys.insert((*j).first); } for (auto j = doubleValues_.begin(); j != doubleValues_.end(); ++j) { keys.insert((*j).first); } for (auto j = keys.begin(); j != keys.end(); ++j) { const std::string& key = (*j); s << bool(true); s << key; auto js = stringValues_.find(key); s << bool(js != stringValues_.end()); if (js != stringValues_.end()) { s << (*js).second; } auto ls = longValues_.find(key); s << bool(ls != longValues_.end()); if (ls != longValues_.end()) { s << (*ls).second; } auto ds = doubleValues_.find(key); s << bool(ds != doubleValues_.end()); if (ds != doubleValues_.end()) { s << (*ds).second; } } s << bool(false); } FieldIndex::~FieldIndex() {} std::string FieldIndex::substitute(const std::string& pattern) const { return eckit::StringTools::substitute(pattern, stringValues_); } void FieldIndex::getValue(const std::string& key, double& value) { std::map::iterator j = doubleValues_.find(key); if (j == doubleValues_.end()) throw eckit::UserError(std::string("FieldIndex::getDouble failed for [") + key + "]"); value = (*j).second; } void FieldIndex::getValue(const std::string& key, long& value) { std::map::iterator j = longValues_.find(key); if (j == longValues_.end()) throw eckit::UserError(std::string("FieldIndex::getLong failed for [") + key + "]"); value = (*j).second; } void FieldIndex::getValue(const std::string& key, std::string& value) { std::map::iterator j = stringValues_.find(key); if (j == stringValues_.end()) throw eckit::UserError(std::string("FieldIndex::getString failed for [") + key + "]"); value = (*j).second; } void FieldIndex::setValue(const std::string& name, double value) { doubleValues_[name] = value; } void FieldIndex::setValue(const std::string& name, long value) { longValues_[name] = value; } void FieldIndex::setValue(const std::string& name, const std::string& value) { stringValues_[name] = value; } } // namespace fields } // namespace metkit metkit-1.16.0/src/metkit/fields/FieldIndex.h000066400000000000000000000027721513171467200206310ustar00rootroot00000000000000/* * (C) Copyright 1996- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ #ifndef metkit_FieldIndex_H #define metkit_FieldIndex_H #include "eckit/memory/NonCopyable.h" #include "eckit/serialisation/Stream.h" namespace eckit { namespace message { class Message; } } // namespace eckit namespace metkit { namespace fields { class FieldIndex : private eckit::NonCopyable { public: FieldIndex(); FieldIndex(const eckit::message::Message&); FieldIndex(eckit::Stream&); virtual ~FieldIndex(); void getValue(const std::string& name, double& value); void getValue(const std::string& name, long& value); void getValue(const std::string& name, std::string& value); std::string substitute(const std::string& pattern) const; void encode(eckit::Stream&) const; void setValue(const std::string& name, double value); void setValue(const std::string& name, long value); void setValue(const std::string& name, const std::string& value); protected: // members std::map stringValues_; std::map longValues_; std::map doubleValues_; }; } // namespace fields } // namespace metkit #endif metkit-1.16.0/src/metkit/fields/FieldIndexList.cc000066400000000000000000000031561513171467200216200ustar00rootroot00000000000000/* * (C) Copyright 1996- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ #include "eckit/exception/Exceptions.h" #include "metkit/fields/FieldIndexList.h" #include "metkit/fields/SimpleFieldIndex.h" namespace metkit { namespace fields { FieldIndexList::~FieldIndexList() { for (size_t i = 0; i < fields_.size(); ++i) { FieldIndex* h = fields_[i]; delete h; } } void FieldIndexList::readFrom(eckit::Stream& s) { ASSERT(length_.size() == 0); ASSERT(offset_.size() == 0); ASSERT(fields_.size() == 0); unsigned long count; s >> count; length_.resize(count); offset_.resize(count); fields_.resize(count); for (size_t i = 0; i < count; ++i) { unsigned long long x; s >> x; offset_[i] = x; s >> x; length_[i] = x; fields_[i] = new SimpleFieldIndex(s); } } void FieldIndexList::sendTo(eckit::Stream& s) const { ASSERT(length_.size() == offset_.size()); ASSERT(offset_.size() == fields_.size()); unsigned long count = length_.size(); s << count; for (size_t i = 0; i < count; ++i) { unsigned long long o = offset_[i]; unsigned long long l = length_[i]; s << o; s << l; fields_[i]->encode(s); } } } // namespace fields } // namespace metkit metkit-1.16.0/src/metkit/fields/FieldIndexList.h000066400000000000000000000016171513171467200214620ustar00rootroot00000000000000/* * (C) Copyright 1996- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ #ifndef metkit_FieldIndexList_H #define metkit_FieldIndexList_H #include "eckit/io/Offset.h" #include "eckit/serialisation/Stream.h" #include "eckit/types/Types.h" namespace metkit { namespace fields { class FieldIndex; class FieldIndexList { public: ~FieldIndexList(); void readFrom(eckit::Stream& s); void sendTo(eckit::Stream& s) const; eckit::OffsetList offset_; eckit::LengthList length_; std::vector fields_; }; } // namespace fields } // namespace metkit #endif metkit-1.16.0/src/metkit/fields/SimpleFieldIndex.cc000066400000000000000000000011771513171467200221370ustar00rootroot00000000000000/* * (C) Copyright 1996- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ #include "metkit/fields/SimpleFieldIndex.h" namespace metkit { namespace fields { SimpleFieldIndex::SimpleFieldIndex(eckit::Stream& s) : FieldIndex(s) {} SimpleFieldIndex::~SimpleFieldIndex() {} } // namespace fields } // namespace metkit metkit-1.16.0/src/metkit/fields/SimpleFieldIndex.h000066400000000000000000000016751513171467200220040ustar00rootroot00000000000000/* * (C) Copyright 1996- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ #ifndef metkit_SimpleFieldIndex_H #define metkit_SimpleFieldIndex_H #include "metkit/fields/FieldIndex.h" namespace metkit { namespace fields { // struct grib_handle; class SimpleFieldIndex : public FieldIndex { public: // -- Contructors SimpleFieldIndex(eckit::Stream&); // -- Destructor virtual ~SimpleFieldIndex() override; // -- Methods private: // members // friend std::ostream& operator<<(std::ostream& s,const SimpleFieldIndex& p) // { p.print(s); return s; } }; } // namespace fields } // namespace metkit #endif metkit-1.16.0/src/metkit/hypercube/000077500000000000000000000000001513171467200171555ustar00rootroot00000000000000metkit-1.16.0/src/metkit/hypercube/HyperCube.cc000066400000000000000000000233261513171467200213600ustar00rootroot00000000000000/* * (C) Copyright 2017- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ #include "metkit/hypercube/HyperCube.h" #include #include "eckit/exception/Exceptions.h" #include "eckit/parser/YAMLParser.h" #include "metkit/mars/MarsLanguage.h" #include "metkit/mars/MarsRequest.h" #include "metkit/mars/Type.h" namespace metkit::hypercube { AxisOrder::AxisOrder() { eckit::Value axis = eckit::YAMLParser::decodeFile(axisYamlFile()); const eckit::Value axesNames = axis["axes"]; for (size_t i = 0; i < axesNames.size(); ++i) { axisIndex_[axesNames[i]] = i + 1; axes_.push_back(axesNames[i]); } } size_t AxisOrder::index(const std::string& axis) const { auto it = axisIndex_.find(axis); if (it == axisIndex_.end()) { return 0; } return it->second; } AxisOrder& AxisOrder::instance() { static AxisOrder instance; return instance; } class Axis { public: Axis(const std::string& name, const std::vector& values) : name_(name), values_(values) {} size_t size() const { return values_.size(); } const std::string& name() const { return name_; } int indexOf(const std::string& v) const { auto j = std::find(values_.begin(), values_.end(), v); if (j == values_.end()) { return -1; } return j - values_.begin(); } const std::string& valueOf(size_t index) const { if (values_.size() <= index) { std::ostringstream oss; oss << "Axis::valueOf no value for [axis=" << name() << ",index=" << index << "]"; throw eckit::UserError(oss.str()); } return values_[index]; } friend std::ostream& operator<<(std::ostream& s, const Axis& a) { s << "Axis[" << a.name_ << "]:"; for (size_t i = 0; i < a.values_.size(); ++i) { s << " " << a.values_[i]; } return s; } private: std::string name_; std::vector values_; }; HyperCube::HyperCube(const metkit::mars::MarsRequest& request) : verb_(request.verb()), cube_(std::vector()) { std::vector dimensions; for (auto& name : AxisOrder::instance().axes()) { std::vector values = request.values(name, true); if (!values.empty()) { Axis* a = new Axis(name, values); axes_.push_back(a); axesByName_[name] = a; dimensions.push_back(values.size()); } } cube_ = eckit::HyperCube(dimensions); count_ = cube_.count(); set_ = std::vector(count_, true); } HyperCube::~HyperCube() { for (auto& a : axes_) { delete a; } } bool HyperCube::contains(const metkit::mars::MarsRequest& r) const { int idx = indexOf(r); return (idx >= 0) and set_[idx]; } bool HyperCube::clear(int idx) { if (idx < 0) return false; if (!set_[idx]) return false; set_[idx] = false; count_--; return true; } bool HyperCube::clear(const metkit::mars::MarsRequest& r) { int idx = indexOf(r); return clear(idx); } int HyperCube::indexOf(const metkit::mars::MarsRequest& r) const { std::vector coords; for (auto& a : axes_) { const std::vector& values = r.values(a->name(), true); if (values.size() == 0) { std::ostringstream oss; oss << "HyperCube::indexOf no value for [" << a->name() << "] in request " << r; throw eckit::UserError(oss.str()); } if (values.size() > 1) { std::ostringstream oss; oss << "HyperCube::indexOf too many values for [" << a->name() << "] in request " << r; throw eckit::UserError(oss.str()); } int n = a->indexOf(values[0]); if (n < 0) { return -1; } coords.push_back(n); } return cube_.index(coords); } enum requestRelation { EMBEDDED, ADJACENT, DISJOINT }; requestRelation getRelation(const metkit::mars::MarsRequest& base, const size_t& baseSize, const metkit::mars::MarsRequest& additional, const size_t additionalSize) { metkit::mars::MarsRequest tmp(base); tmp.merge(additional); // creates the bounding box request /// @todo: building a hypercube *JUST* to get the size? Seems like we can do better size_t sizeAfter = tmp.count(); if (sizeAfter == baseSize) return requestRelation::EMBEDDED; if (baseSize + additionalSize == sizeAfter) return requestRelation::ADJACENT; return requestRelation::DISJOINT; } // Returns true only if the last request was merged into an adjacent bool mergeLast(std::vector>& requests) { size_t last = requests.size() - 1; size_t candidateIdx = std::numeric_limits::max(); size_t candidateSize = 0; // check if the new request is embedded or adjacent to existing requests for (size_t j = 0; j < requests.size() - 1; j++) { requestRelation relation = getRelation(requests[j].first, requests[j].second, requests[last].first, requests[last].second); if (relation == requestRelation::EMBEDDED) { requests.pop_back(); return false; } if (relation == requestRelation::ADJACENT) { // We can merge the two requests // Though we will only merge with the largest adjacent request, so dont merge yet. size_t combinedSize = requests[j].second + requests[last].second; if (candidateSize < combinedSize) { candidateIdx = j; candidateSize = combinedSize; } } } // Merge with the largest adjacent request if one was found if (candidateIdx != std::numeric_limits::max()) { requests[candidateIdx].first.merge(requests[last].first); requests[candidateIdx].second += requests[last].second; requests.pop_back(); return true; } return false; } std::vector> HyperCube::request(const std::set& idxs) const { using IndexSet = std::set; ASSERT(idxs.size() > 0); if (idxs.size() <= 1) { return {{requestOf(*idxs.begin()), 1}}; } // -- helper lambdas -------------------------------------------- // Partition the cube into a set of slices along the given axis. const auto sliceAlongAxis = [&](const IndexSet& set, std::size_t axis) { std::map slices; std::vector coords(axes_.size()); for (std::size_t idx : set) { cube_.coordinates(idx, coords); slices[coords[axis]].insert(idx); } return slices; }; // Pick the axis which can be partitioned into the smallest number of slices (>1). const auto pickBestAxis = [&](const IndexSet& set) -> std::size_t { std::size_t bestAxis = 0; std::size_t bestNSlices = std::numeric_limits::max(); for (std::size_t axis = 0; axis < axes_.size(); ++axis) { const std::size_t nSlices = sliceAlongAxis(set, axis).size(); if (nSlices > 1 && nSlices < bestNSlices) { bestAxis = axis; bestNSlices = nSlices; } } ASSERT(bestNSlices != std::numeric_limits::max()); return bestAxis; }; // --------------------------------------------------------------- const std::size_t axis = pickBestAxis(idxs); const auto slices = sliceAlongAxis(idxs, axis); std::vector> result; // Process each slice recursively, appending and merging on the fly. for (const auto& [coord, subIdxs] : slices) { auto subRequests = request(subIdxs); // recursion result.insert(result.end(), subRequests.begin(), subRequests.end()); while (mergeLast(result)) {} } return result; } std::vector HyperCube::aggregatedRequests(bool remaining) const { if (countVacant() == (remaining ? 0 : size())) return std::vector{}; std::set idxs; for (size_t i = 0; i < set_.size(); ++i) { if (set_[i] == remaining) idxs.emplace(i); } std::vector> requests = request(idxs); std::vector out; for (auto req : requests) out.push_back(req.first); return out; } metkit::mars::MarsRequest HyperCube::requestOf(size_t index) const { metkit::mars::MarsRequest request(verb_); std::vector coords(axes_.size()); cube_.coordinates(index, coords); for (size_t i = 0; i < axes_.size(); i++) { request.setValue(axes_[i]->name(), axes_[i]->valueOf(coords[i])); } return request; } size_t HyperCube::count() const { return count_; } size_t HyperCube::countVacant() const { return count_; } size_t HyperCube::fieldOrdinal(const metkit::mars::MarsRequest& r, bool noholes) const { int idx = indexOf(r); ASSERT(idx >= 0); if (noholes) { size_t p = 0; for (size_t i = 0; i < idx; ++i) { if (set_[i]) { p++; } } return p; } return idx; } void HyperCube::print(std::ostream& s) const { NOTIMP; ///@todo } } // namespace metkit::hypercube metkit-1.16.0/src/metkit/hypercube/HyperCube.h000066400000000000000000000053451513171467200212230ustar00rootroot00000000000000/* * (C) Copyright 2017- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ /// @author Baudouin Raoult /// @date Aug 2017 #ifndef metkit_HyperCube_H #define metkit_HyperCube_H #include #include #include #include #include "eckit/utils/HyperCube.h" #include "metkit/config/LibMetkit.h" #include "metkit/mars/MarsRequest.h" namespace metkit { namespace hypercube { class Axis; class AxisOrder { public: // methods static AxisOrder& instance(); const std::vector& axes() { return axes_; } size_t index(const std::string& axis) const; private: // methods AxisOrder(); eckit::PathName axisYamlFile() { return "~metkit/share/metkit/axis.yaml"; } private: // members std::vector axes_; std::map axisIndex_; }; class HyperCube { public: HyperCube(const metkit::mars::MarsRequest&); ~HyperCube(); bool contains(const metkit::mars::MarsRequest&) const; bool clear(const metkit::mars::MarsRequest&); size_t count() const; size_t countVacant() const; size_t size() const { return cube_.count(); } size_t fieldOrdinal(const metkit::mars::MarsRequest&, bool noholes = true) const; std::vector vacantRequests() const { return aggregatedRequests(true); } std::vector requests() const { return aggregatedRequests(false); } protected: std::vector aggregatedRequests(bool remaining) const; int indexOf(const metkit::mars::MarsRequest&) const; bool clear(int index); metkit::mars::MarsRequest requestOf(size_t index) const; // Given a set of indices, build the *minimal* collection of Mars requests that cover them. // Each entry in the result vector is: { merged_request, number_of_points_covered_by_that_request } /// @note: This does not take into account whether the point is "set" or not std::vector> request(const std::set& idxs) const; private: std::string verb_; std::vector axes_; std::map axesByName_; std::vector set_; eckit::HyperCube cube_; size_t count_; void print(std::ostream&) const; friend std::ostream& operator<<(std::ostream& s, const HyperCube& p) { p.print(s); return s; } }; } // namespace hypercube } // namespace metkit #endif metkit-1.16.0/src/metkit/hypercube/HyperCubePayloaded.h000066400000000000000000000036221513171467200230420ustar00rootroot00000000000000/* * (C) Copyright 2017- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ /// @author Emanuele Danovaro /// @date Aug 2020 #ifndef metkit_HyperCubePayloaded_H #define metkit_HyperCubePayloaded_H #include "metkit/hypercube/HyperCube.h" namespace metkit { namespace hypercube { template class Deduplicator { public: virtual bool toReplace(const T& existing, const T& replacement) const = 0; }; template class HyperCubePayloaded : public HyperCube { public: HyperCubePayloaded(const metkit::mars::MarsRequest& request, const Deduplicator& deduplicator) : HyperCube(request), dedup_(deduplicator) { // throw error for default dedup } void add(const metkit::mars::MarsRequest& request, T payload) { int idx = indexOf(request); ASSERT(0 <= idx && idx < size()); auto entry = entries_.find(idx); if (entry == entries_.end()) { entries_.emplace(idx, payload); clear(idx); } else { if (dedup_.toReplace(entry->second, payload)) { entry->second = payload; } } } const T& at(size_t idx) { ASSERT(0 <= idx); ASSERT(idx < size()); return entries_[idx]; } bool find(size_t idx, T& payload) { auto it = entries_.find(idx); if (it == entries_.end()) return false; payload = it->second; return true; } private: const Deduplicator& dedup_; std::map entries_; }; } // namespace hypercube } // namespace metkit #endif metkit-1.16.0/src/metkit/mars/000077500000000000000000000000001513171467200161315ustar00rootroot00000000000000metkit-1.16.0/src/metkit/mars/BaseProtocol.cc000066400000000000000000000061361513171467200210420ustar00rootroot00000000000000/* * (C) Copyright 1996- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ // File BaseProtocol.cc // Baudouin Raoult - (c) ECMWF Feb 12 #include "metkit/mars/BaseProtocol.h" #include "eckit/config/Configuration.h" #include "eckit/exception/Exceptions.h" #include "eckit/thread/AutoLock.h" #include "eckit/thread/Mutex.h" #include "eckit/thread/Once.h" namespace metkit { namespace mars { static eckit::Mutex* local_mutex = 0; static std::map* m = 0; static pthread_once_t once = PTHREAD_ONCE_INIT; static void init() { local_mutex = new eckit::Mutex(); m = new std::map(); } BaseProtocol::BaseProtocol() {} BaseProtocol::BaseProtocol(eckit::Stream& s) : eckit::Streamable(s) {} BaseProtocol::BaseProtocol(const eckit::Configuration&) {} BaseProtocol::~BaseProtocol() {} const eckit::ClassSpec& BaseProtocol::classSpec() { static eckit::ClassSpec spec = {&Streamable::classSpec(), "BaseProtocol"}; return spec; } void BaseProtocol::encode(eckit::Stream& s) const { eckit::Streamable::encode(s); } //======================================================================== ProtocolFactory::ProtocolFactory(const std::string& name) : name_(name) { pthread_once(&once, init); eckit::AutoLock lock(local_mutex); if (m->find(name) != m->end()) { throw eckit::SeriousBug("ProtocolFactory: duplication action: " + name); } ASSERT(m->find(name) == m->end()); (*m)[name] = this; } ProtocolFactory::~ProtocolFactory() { eckit::AutoLock lock(local_mutex); m->erase(name_); } BaseProtocol* ProtocolFactory::build(const eckit::Configuration& params) { pthread_once(&once, init); eckit::AutoLock lock(local_mutex); const std::string& name = params.getString("class"); std::map::const_iterator j = m->find(name); if (j == m->end()) { if (j == m->end()) { eckit::Log::error() << "No ProtocolFactory for [" << name << "]" << std::endl; eckit::Log::error() << "ProtocolFactories are:" << std::endl; for (j = m->begin(); j != m->end(); ++j) eckit::Log::error() << " " << (*j).first << std::endl; throw eckit::SeriousBug(std::string("No ProtocolFactory called ") + name); } } return (*j).second->make(params); } void ProtocolFactory::list(std::ostream& out) { pthread_once(&once, init); eckit::AutoLock lock(local_mutex); const char* sep = ""; for (std::map::const_iterator j = m->begin(); j != m->end(); ++j) { out << sep << (*j).first; sep = ", "; } } } // namespace mars } // namespace metkit metkit-1.16.0/src/metkit/mars/BaseProtocol.h000066400000000000000000000041661513171467200207050ustar00rootroot00000000000000/* * (C) Copyright 1996- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ // File BaseProtocol.h // Baudouin Raoult - (c) ECMWF Feb 12 #ifndef BaseProtocol_H #define BaseProtocol_H #include "eckit/io/Length.h" #include "eckit/serialisation/Streamable.h" namespace eckit { class Configuration; } namespace metkit { namespace mars { class MarsRequest; class BaseProtocol : public eckit::Streamable { public: BaseProtocol(); BaseProtocol(eckit::Stream&); BaseProtocol(const eckit::Configuration&); virtual ~BaseProtocol() override; virtual eckit::Length retrieve(const MarsRequest&) = 0; virtual void archive(const MarsRequest&, const eckit::Length&) = 0; virtual long read(void* buffer, long len) = 0; virtual long write(const void* buffer, long len) = 0; virtual void cleanup() = 0; // -- Overridden methods (from Streamable) static const eckit::ClassSpec& classSpec(); protected: virtual void print(std::ostream&) const = 0; virtual void encode(eckit::Stream&) const override; private: friend std::ostream& operator<<(std::ostream& s, const BaseProtocol& p) { p.print(s); return s; } }; class ProtocolFactory { std::string name_; virtual BaseProtocol* make(const eckit::Configuration&) = 0; protected: ProtocolFactory(const std::string&); virtual ~ProtocolFactory(); public: static BaseProtocol* build(const eckit::Configuration&); static void list(std::ostream&); }; template class ProtocolBuilder : public ProtocolFactory { virtual BaseProtocol* make(const eckit::Configuration& param) override { return new T(param); } public: ProtocolBuilder(const std::string& name) : ProtocolFactory(name) {} }; } // namespace mars } // namespace metkit #endif metkit-1.16.0/src/metkit/mars/ClientTask.cc000066400000000000000000000034551513171467200205100ustar00rootroot00000000000000/* * (C) Copyright 1996- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ #include #include #include "metkit/mars/ClientTask.h" #include "metkit/mars/MarsHandle.h" namespace metkit { namespace mars { // Call by the clien code ClientTask::ClientTask(const MarsRequest& r, const MarsRequest& e, const std::string& host, int port, unsigned long long id) : request_(r), environ_(e), metkitID_(id), port_(port), host_(host), handle_() { // Try something unique (per machine) // Warning: Servers recovers time(0) from ID // to compute request age. Not good if (!metkitID_) { typedef unsigned long long ull; metkitID_ = (ull(::getpid()) << ull(32 + 16)) | (ull(::pthread_self()) << ull(32)) | (ull(::time(0)) & ull(0xffffffff)); } handle_.reset(new MarsHandle(host_, port_, metkitID_)); } ClientTask::~ClientTask() {} void ClientTask::send(eckit::Stream& s) const { unsigned long long dummy = 0; s.startObject(); s << "MarsTask"; /* send mars request id */ s << dummy; /* Send requests */ s << request_; s << environ_; /* Send cb info */ s << host_; s << port_; s << metkitID_; /* Send datahandle */ s << *handle_; s.endObject(); } char ClientTask::receive(eckit::Stream& s) const { unsigned long long id; char mode; s >> id; ASSERT(id == metkitID_); s >> mode; return mode; } } // namespace mars } // namespace metkit metkit-1.16.0/src/metkit/mars/ClientTask.h000066400000000000000000000117171513171467200203520ustar00rootroot00000000000000/* * (C) Copyright 1996- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ // File ClientTask.h // Baudouin Raoult - ECMWF Oct 96 #ifndef metkit_ClientTask_H #define metkit_ClientTask_H #include // #include "eckit/bases/Watcher.h" #include "eckit/exception/Exceptions.h" #include "eckit/io/DataHandle.h" // #include "eckit/log/UserChannel.h" #include "eckit/transaction/TxnEvent.h" #include "metkit/mars/MarsRequest.h" namespace metkit { namespace mars { class ClientTask { public: // -- Contructors ClientTask(const MarsRequest&, const MarsRequest&, const std::string& name, int port, unsigned long long id = 0); // ClientTask(eckit::Stream&); // -- Destructor ~ClientTask(); // -- Convertors // None // -- Operators // None // -- Methods // void dump(std::ostream&) const; // void json(eckit::JSON&) const; // MarsInfo info() const; // const MarsID& id() const { return transactionID(); } // const MarsRequest& request() const { return request_; } // const MarsRequest& environ() const { return environ_; } // eckit::Length transferData(const eckit::PathName&); // eckit::PathName transferData(); // /// @returns eckit::DataHandle with the data that will be received, but does not give ownership of the // eckit::DataHandle eckit::DataHandle& getDataHandle(); // void sendData(eckit::DataHandle&); // void sendHandle(eckit::DataHandle&); // void acknowledge(eckit::Stream& s) { send(s,'a'); } // void patch(); // bool authenticated() const; // eckit::DataHandle& dataHandle() { return *handle_; } // // Report // void success(); // void failure(const std::string&); // void retry(const std::string&); // void infoMsg(const std::string&); // void warningMsg(const std::string&); // void errorMsg(const std::string&); // void notifyClient(const std::string&); // void notifyStart(); // void queueTime(); // void ping(); // void sendCost(); // void sendChecksum(const std::string&); // // Queuing // double startingPriority() const { return startingPriority_;} // void startingPriority(double p) { startingPriority_ = p;} // // Cost // Cost& cost() { return cost_; } // const Cost& cost() const { return cost_; } // void costChanged(); // // Called by PipeProcess // void send(eckit::Stream&); // void reply(eckit::Stream&); // bool error(std::exception&,int); // void done(); // Logging // Mars tree // void push(const std::string&,const std::string&); // void pop(); // void reset(); // const eckit::StringList& treeNames() const { return treeNames_; } // const eckit::StringList& treeValues() const { return treeValues_; } // // For the metkit void send(eckit::Stream&) const; char receive(eckit::Stream&) const; // -- Overridden methods // From Streamble // virtual void encode(eckit::Stream&) const override; // virtual const eckit::ReanimatorBase& reanimator() const { return reanimator_; } // From watcher // virtual void watch(); // -- Class methods // static const eckit::ClassSpec& classSpec() { return classSpec_;} // static void recover(TxnRecoverer&); // static void find(TxnFinder&); // static std::string commandName(); // None protected: // -- Members MarsRequest request_; MarsRequest environ_; private: // -- Members // unsigned long long txnID_; // unused unsigned long long metkitID_; int port_; std::string host_; std::unique_ptr handle_; std::string checksum_; // Not sent over streams // double startingPriority_; // Cost cost_; // time_t lastPing_; // time_t queueTime_; // eckit::StringList treeValues_; // eckit::StringList treeNames_; // bool authenticated_; // -- Methods // void print(std::ostream&) const; // void send(eckit::Stream&,char) const; // -- Overridden methods // None // -- Class members // static eckit::ClassSpec classSpec_; // static eckit::Reanimator reanimator_; // -- Class methods // None // friend std::ostream& operator<<(std::ostream& s, const ClientTask& r) // { r.print(s); return s; } // friend eckit::JSON& operator<<(eckit::JSON& s, const ClientTask& r) // { r.json(s); return s; } }; } // namespace mars } // namespace metkit #endif metkit-1.16.0/src/metkit/mars/ContextRule.h000066400000000000000000000011571513171467200205620ustar00rootroot00000000000000/* * (C) Copyright 2025- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ #pragma once #include "metkit/mars/MarsRequest.h" namespace metkit::mars { //---------------------------------------------------------------------------------------------------------------------- } // namespace metkit::mars metkit-1.16.0/src/metkit/mars/DHSProtocol.cc000066400000000000000000000435101513171467200206030ustar00rootroot00000000000000/* * (C) Copyright 1996- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ // File DHSProtocol.cc // Baudouin Raoult - (c) ECMWF Feb 12 #include "metkit/mars/DHSProtocol.h" #include "eckit/config/Configuration.h" #include "eckit/config/Resource.h" #include "eckit/io/AutoCloser.h" #include "eckit/net/Endpoint.h" #include "eckit/net/IPAddress.h" #include "eckit/net/TCPClient.h" #include "eckit/net/TCPStream.h" #include "eckit/utils/StringTools.h" #include "eckit/utils/Translator.h" #include "metkit/config/LibMetkit.h" #include "metkit/mars/ClientTask.h" #include "metkit/mars/RequestEnvironment.h" using namespace eckit; using eckit::net::Endpoint; namespace metkit { namespace mars { static Reanimator dhsProtocolReanimator; // --------------------------------------------------------------------------------------------------------------------- namespace { constexpr const int DEFAULT_CALLBACK_PROXY_PORT = 9707; // Normally we would let the Endpoint constructor do this unpacking itself, but we want to set a default port Endpoint unpackHostPort(const std::string& hoststr) { auto bits = StringTools::split(":", hoststr); ASSERT(!bits.empty() && bits.size() < 3); int port = DEFAULT_CALLBACK_PROXY_PORT; if (bits.size() == 2) { port = Translator()(bits[1]); } return {bits[0], port}; } Endpoint selectProxyHost(const std::vector proxies) { return unpackHostPort(proxies[std::rand() % proxies.size()]); } Endpoint selectProxyHost(const Configuration& config) { if (config.has("proxyHost")) { return unpackHostPort(config.getString("proxyHost")); } if (config.has("proxyHosts")) { return selectProxyHost(config.getStringVector("proxyHosts")); } throw UserError("Neither proxyHosts nor proxyHost specified in configuration"); } } // namespace // Implement the default callback behaviour. Client opens a socket that can be connected to by // the server or data mover class SimpleCallback : public BaseCallbackConnection { public: SimpleCallback() : callback_(Resource("$MARS_DHS_LOCALPORT", 0)), callbackEndpoint_(computeEndpoint()) { LOG_DEBUG_LIB(LibMetkit) << "Simple callback. local port=" << callback_.localPort() << " host=" << callbackEndpoint_.host() << " port=" << callbackEndpoint_.port() << std::endl; } explicit SimpleCallback(const Configuration&) : SimpleCallback() {} explicit SimpleCallback(Stream&) : SimpleCallback() {} private: const Endpoint& endpoint() const override { return callbackEndpoint_; } net::TCPSocket& connect() override { return callback_.accept(); } net::EphemeralTCPServer callback_; Endpoint callbackEndpoint_; Endpoint computeEndpoint() const { static std::string callbackHost = Resource("$MARS_DHS_CALLBACK_HOST", ""); static int callbackPort = Resource("$MARS_DHS_CALLBACK_PORT", 0); if (callbackHost.empty()) { return Endpoint{net::IPAddress::hostAddress(callback_.localHost()).asString(), callback_.localPort()}; } if (callbackPort == 0) { return Endpoint{callbackHost, callback_.localPort()}; } return Endpoint{callbackHost, callbackPort}; } public: static const ClassSpec& classSpec() { static ClassSpec spec = {&BaseCallbackConnection::classSpec(), "SimpleCallback"}; return spec; } protected: const ReanimatorBase& reanimator() const override { return reanimator_; } void encode(Stream&) const override {} static Reanimator reanimator_; }; Reanimator SimpleCallback::reanimator_; // --------------------------------------------------------------------------------------------------------------------- // Implement a callback via the callback proxy. First we open a connection to the proxy. This then returns to us // the host/port that it has made available for the server/mover to connect to. It then proxies the connection // to our host/port class ProxyCallback : public BaseCallbackConnection { public: explicit ProxyCallback(const Endpoint& proxyhost) : control_(net::TCPClient().connect(proxyhost)), proxyHost_(proxyhost) { LOG_DEBUG_LIB(LibMetkit) << "Proxy callback. proxyhost=" << proxyhost.host() << " proxyport=" << proxyhost.port() << std::endl; std::string localAddr = net::IPAddress::hostAddress(callback_.localHost()).asString(); int localPort = callback_.localPort(); bool passive = false; control_ << localAddr; control_ << localPort; control_ << passive; remoteAddr_ = Endpoint(control_); } explicit ProxyCallback(const Configuration& config) : ProxyCallback(selectProxyHost(config)) {} explicit ProxyCallback(Stream& s) : ProxyCallback(Endpoint(s)) {} private: const Endpoint& endpoint() const override { return remoteAddr_; } net::TCPSocket& connect() override { // FIXME: Check that the callback connection is still alive... return callback_.accept(); } net::TCPStream control_; net::EphemeralTCPServer callback_; Endpoint proxyHost_; Endpoint remoteAddr_; public: static const ClassSpec& classSpec() { static ClassSpec spec = {&BaseCallbackConnection::classSpec(), "ProxyCallback"}; return spec; } protected: const ReanimatorBase& reanimator() const override { return reanimator_; } void encode(Stream& s) const override { s << proxyHost_; } static Reanimator reanimator_; }; Reanimator ProxyCallback::reanimator_; // --------------------------------------------------------------------------------------------------------------------- // Implement a callback via the callback proxy using passive mode. First we open a connection to the proxy. // This then returns to us the host/port that it has made available for the server/mover to connect to. // We then need to open connections to the proxy for the callbacks to connect to. class PassiveProxyCallback : public BaseCallbackConnection { public: explicit PassiveProxyCallback(const Endpoint& proxyhost, bool useProxyHostAsCallback = true) : control_(net::TCPClient().connect(proxyhost)), proxyHost_(proxyhost) { LOG_DEBUG_LIB(LibMetkit) << "Passive proxy callback. proxyhost=" << proxyhost << std::endl; std::string localAddr = ""; int localPort = -1; bool passive = true; control_ << localAddr; control_ << localPort; control_ << passive; remoteAddr_ = Endpoint(control_); LOG_DEBUG_LIB(LibMetkit) << "Remote address. host=" << remoteAddr_ << std::endl; passiveAddr_ = Endpoint(control_); if (useProxyHostAsCallback) { passiveAddr_ = Endpoint(proxyhost.host(), passiveAddr_.port()); } LOG_DEBUG_LIB(LibMetkit) << "Passive address. host=" << passiveAddr_ << std::endl; control_ >> passiveCheck_; LOG_DEBUG_LIB(LibMetkit) << "Passive address. host=" << passiveAddr_ << " check=" << passiveCheck_ << std::endl; } explicit PassiveProxyCallback(const Configuration& config) : PassiveProxyCallback(selectProxyHost(config), config.getBool("useProxyHostAsCallback", true)) {} explicit PassiveProxyCallback(Stream& s) : PassiveProxyCallback(Endpoint(s)) {} private: const Endpoint& endpoint() const override { return remoteAddr_; } net::TCPSocket& connect() override { // FIXME: Check that the callback connection is still alive... ASSERT(!socket_.isConnected()); socket_ = net::TCPClient().connect(passiveAddr_); net::InstantTCPStream s(socket_); s << passiveCheck_; return socket_; } net::TCPStream control_; net::TCPSocket socket_; Endpoint proxyHost_; Endpoint remoteAddr_; Endpoint passiveAddr_; unsigned long long passiveCheck_; public: static const ClassSpec& classSpec() { static ClassSpec spec = {&BaseCallbackConnection::classSpec(), "PassiveProxyCallback"}; return spec; } protected: const ReanimatorBase& reanimator() const override { return reanimator_; } void encode(Stream& s) const override { s << proxyHost_; } static Reanimator reanimator_; }; Reanimator PassiveProxyCallback::reanimator_; // --------------------------------------------------------------------------------------------------------------------- const ClassSpec& BaseCallbackConnection::classSpec() { static ClassSpec spec = {&Streamable::classSpec(), "BaseCallbackConnection"}; return spec; } BaseCallbackConnection* BaseCallbackConnection::build(const Configuration& config, const std::string& host) { if (config.has("proxyHost") || config.has("proxyHosts") || (config.getBool("passiveProxy", true) && config.getBool("useHostAsProxy", false))) { if (config.getBool("passiveProxy", true)) { if (config.getBool("useHostAsProxy", false)) { return new PassiveProxyCallback{unpackHostPort(host)}; } return new PassiveProxyCallback{config}; } return new ProxyCallback{config}; } static bool passiveProxy = Resource("$MARS_DHS_PASSIVE_PROXY", true); static std::vector proxyHosts = Resource>("$MARS_DHS_CALLBACK_PROXY_HOST", {}); if (!proxyHosts.empty()) { Endpoint proxyHost = selectProxyHost(proxyHosts); if (passiveProxy) { return new PassiveProxyCallback(proxyHost); } else { return new ProxyCallback(proxyHost); } } return new SimpleCallback{config}; } // --------------------------------------------------------------------------------------------------------------------- DHSProtocol::DHSProtocol(const std::string& name, const std::string& host, int port, bool forwardMessages) : callback_(new SimpleCallback{}), name_(name), host_(host), port_(port), done_(false), error_(false), sending_(false), forward_(forwardMessages) {} DHSProtocol::DHSProtocol(const Configuration& params) : BaseProtocol(params), name_(params.getString("name")), port_(params.getInt("port", 9000)), done_(false), error_(false), sending_(false), forward_(false) { if (params.has("hosts")) { std::vector hosts = params.getStringVector("hosts"); host_ = hosts.at(std::rand() % hosts.size()); } else { ASSERT(params.has("host")); host_ = params.getString("host"); } env_ = RequestEnvironment::instance().request(); callback_.reset(BaseCallbackConnection::build(params, host_)); } DHSProtocol::DHSProtocol(const Configuration& params, const std::map& env) : DHSProtocol(params) { RequestEnvironment requestEnv{RequestEnvironment::instance()}; requestEnv.update(env); env_ = requestEnv.request(); } DHSProtocol::DHSProtocol(Stream& s) : BaseProtocol(s), callback_(Reanimator::reanimate(s)) { s >> name_; s >> host_; s >> port_; s >> done_; s >> error_; s >> sending_; s >> forward_; env_ = MarsRequest(s); } DHSProtocol::~DHSProtocol() { done_ = true; cleanup(); } const ReanimatorBase& DHSProtocol::reanimator() const { return dhsProtocolReanimator; } const ClassSpec& DHSProtocol::classSpec() { static ClassSpec spec = {&BaseProtocol::classSpec(), "DHSProtocol"}; return spec; } Length DHSProtocol::retrieve(const MarsRequest& request) { Endpoint callbackEndpoint = callback_->endpoint(); LOG_DEBUG_LIB(LibMetkit) << "DHSProtocol: call back on " << callbackEndpoint << std::endl; task_.reset(new ClientTask(request, env_, callbackEndpoint.host(), callbackEndpoint.port())); net::TCPStream s(net::TCPClient().connect(host_, port_)); task_->send(s); ASSERT(task_->receive(s) == 'a'); // Acknoledgement Length result = 0; while (wait(result)) {} LOG_DEBUG_LIB(LibMetkit) << "DHSProtocol::retrieve " << result << std::endl; return result; } void DHSProtocol::archive(const MarsRequest& request, const Length& size) { Endpoint callbackEndpoint = callback_->endpoint(); LOG_DEBUG_LIB(LibMetkit) << "DHSProtocol::archive " << size << std::endl; LOG_DEBUG_LIB(LibMetkit) << "DHSProtocol: call back on " << callbackEndpoint << std::endl; task_.reset(new ClientTask(request, env_, callbackEndpoint.host(), callbackEndpoint.port())); net::TCPStream s(net::TCPClient().connect(host_, port_)); task_->send(s); ASSERT(task_->receive(s) == 'a'); // Acknoledgement Length result = size; while (wait(result)) {} LOG_DEBUG_LIB(LibMetkit) << "DHSProtocol: archive completed." << std::endl; } void DHSProtocol::cleanup() { if (socket_.isConnected()) { if (sending_) { unsigned long version = 1; unsigned long long crc = 0; try { net::InstantTCPStream s(socket_); s << version; s << crc; } catch (std::exception& e) { Log::error() << "** " << e.what() << " Caught in " << Here() << std::endl; Log::error() << "** Exception is ignored" << std::endl; } } socket_.close(); } sending_ = false; if (!done_) { Length result = 0; while (wait(result)) { ; } } if (error_) { error_ = false; throw UserError(std::string("Error from [") + name_ + "]: " + msg_); } } void DHSProtocol::print(std::ostream& s) const { s << "DHSProtocol[" << name_ << "]"; } void DHSProtocol::encode(Stream& s) const { BaseProtocol::encode(s); callback_->encode(s); s << name_; s << host_; s << port_; s << done_; s << error_; s << sending_; s << forward_; s << env_; } long DHSProtocol::read(void* buffer, long len) { return socket_.read(buffer, len); } long DHSProtocol::write(const void* buffer, long len) { return socket_.write(buffer, len); } bool DHSProtocol::wait(Length& size) { for (;;) { if (socket_.isConnected()) socket_.close(); socket_ = callback_->connect(); net::InstantTCPStream s(socket_); char code = task_->receive(s); LOG_DEBUG_LIB(LibMetkit) << "DHSProtocol: code [" << code << "]" << std::endl; std::string msg; long long bytes; switch (code) { /* OK */ case 'o': done_ = true; return false; /* read source */ case 'r': bytes = size; LOG_DEBUG_LIB(LibMetkit) << "DHSProtocol:r [" << bytes << "]" << std::endl; s << bytes; sending_ = true; return false; /* get */ case 'h': NOTIMP; case 'w': s >> bytes; LOG_DEBUG_LIB(LibMetkit) << "DHSProtocol:w " << bytes << std::endl; size = bytes; return false; case 'm': NOTIMP; case 'X': NOTIMP; case 'e': s >> msg_; Log::error() << msg_ << " [" << name_ << "]" << std::endl; error_ = true; done_ = true; return false; case 'y': /* retry */ NOTIMP; case 'I': /* info */ s >> msg; Log::info() << msg << " [" << name_ << "]" << std::endl; if (forward_) { Log::userInfo() << msg << " [" << name_ << "]" << std::endl; } break; case 'W': /* warning */ s >> msg; Log::warning() << msg << " [" << name_ << "]" << std::endl; if (forward_) { Log::userWarning() << msg << " [" << name_ << "]" << std::endl; } break; case 'D': /* debug */ s >> msg; LOG_DEBUG_LIB(LibMetkit) << msg << " [" << name_ << "]" << std::endl; if (forward_) { Log::userInfo() << msg << " [" << name_ << "]" << std::endl; } break; case 'E': /* error */ s >> msg; Log::error() << msg << " [" << name_ << "]" << std::endl; if (forward_) { Log::userError() << msg << " [" << name_ << "]" << std::endl; } break; case 'N': /* notification */ NOTIMP; case 'p': /* ping */ s << 'p'; break; case 's': /* statistics */ { int n; s >> n; std::string key, value; for (int i = 0; i < n; i++) { s >> key >> value; Log::info() << "DHSProtocol:s " << key << "=" << value << std::endl; } } break; case 'S': /* notification start */ NOTIMP; case 't': /* new timeout */ NOTIMP; default: throw Exception(std::string("Unknown code [") + code + "]"); } } } static ProtocolBuilder builder("dhsbase"); } // namespace mars } // namespace metkit metkit-1.16.0/src/metkit/mars/DHSProtocol.h000066400000000000000000000060701513171467200204450ustar00rootroot00000000000000/* * (C) Copyright 1996- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ // File DHSProtocol.h // Baudouin Raoult - (c) ECMWF Feb 12 #ifndef DHSProtocol_H #define DHSProtocol_H #include #include "eckit/net/Endpoint.h" #include "eckit/net/TCPServer.h" #include "eckit/net/TCPSocket.h" #include "metkit/mars/BaseProtocol.h" #include "metkit/mars/ClientTask.h" #include "metkit/mars/MarsRequest.h" namespace metkit { namespace mars { // --------------------------------------------------------------------------------------------------------------------- class BaseCallbackConnection : public eckit::Streamable { public: BaseCallbackConnection() {} virtual ~BaseCallbackConnection() {} static BaseCallbackConnection* build(const eckit::Configuration& config, const std::string& host = ""); virtual const eckit::net::Endpoint& endpoint() const = 0; virtual eckit::net::TCPSocket& connect() = 0; virtual void encode(eckit::Stream&) const override = 0; static const eckit::ClassSpec& classSpec(); }; // --------------------------------------------------------------------------------------------------------------------- class DHSProtocol : public BaseProtocol { public: DHSProtocol(const eckit::Configuration&); DHSProtocol(const eckit::Configuration&, const std::map& env); DHSProtocol(const std::string& name, const std::string& host, int port, bool forewardMessages = false); DHSProtocol(eckit::Stream&); ~DHSProtocol(); // -- Overridden methods (from Streamable) virtual std::string className() const override { return "DHSProtocol"; } virtual const eckit::ReanimatorBase& reanimator() const override; static const eckit::ClassSpec& classSpec(); private: // -- Members std::unique_ptr callback_; eckit::net::TCPSocket socket_; std::string name_; std::string host_; int port_; std::string msg_; std::unique_ptr task_; bool done_; bool error_; bool sending_; bool forward_; MarsRequest env_; // -- Methods bool wait(eckit::Length&); // -- Overridden methods // From BaseProtocol virtual eckit::Length retrieve(const MarsRequest& request) override; virtual void archive(const MarsRequest& request, const eckit::Length&) override; virtual long read(void* buffer, long len) override; virtual long write(const void* buffer, long len) override; virtual void cleanup() override; virtual void print(std::ostream&) const override; virtual void encode(eckit::Stream&) const override; }; // --------------------------------------------------------------------------------------------------------------------- } // namespace mars } // namespace metkit #endif metkit-1.16.0/src/metkit/mars/MarsExpandContext.h000066400000000000000000000023441513171467200217140ustar00rootroot00000000000000/* * (C) Copyright 1996- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ /// @author Manuel Fuentes /// @author Baudouin Raoult /// @author Tiago Quintino /// @date Sep 96 #pragma once #include namespace metkit::mars { //---------------------------------------------------------------------------------------------------------------------- class [[deprecated]] MarsExpandContext { void info(std::ostream&) const {} public: friend std::ostream& operator<<(std::ostream& s, const MarsExpandContext& r) { return s; } }; //---------------------------------------------------------------------------------------------------------------------- class [[deprecated]] DummyContext : public MarsExpandContext { using MarsExpandContext::MarsExpandContext; }; //---------------------------------------------------------------------------------------------------------------------- } // namespace metkit::mars metkit-1.16.0/src/metkit/mars/MarsExpansion.cc000066400000000000000000000053421513171467200212330ustar00rootroot00000000000000/* * (C) Copyright 1996- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ #include "metkit/mars/MarsExpansion.h" #include "metkit/mars/MarsLanguage.h" namespace metkit::mars { //---------------------------------------------------------------------------------------------------------------------- FlattenCallback::~FlattenCallback() = default; ExpandCallback::~ExpandCallback() = default; //---------------------------------------------------------------------------------------------------------------------- MarsExpansion::MarsExpansion(bool inherit, bool strict) : inherit_(inherit), strict_(strict) {} MarsExpansion::~MarsExpansion() { for (auto& language : languages_) { delete language.second; } } void MarsExpansion::reset() { for (auto& language : languages_) { language.second->reset(); } } MarsLanguage& MarsExpansion::language(const std::string& verb) { auto v = MarsLanguage::expandVerb(verb); if (auto j = languages_.find(v); j != languages_.end()) { return *(*j).second; } auto j = languages_.emplace(v, new MarsLanguage(v)).first; return *(*j).second; } std::vector MarsExpansion::expand(const std::vector& requests) { std::vector result; result.reserve(requests.size()); // Implement inheritence for (const auto& request : requests) { auto& lang = language(request.verb()); result.emplace_back(lang.expand(request, inherit_, strict_)); } return result; } MarsRequest MarsExpansion::expand(const MarsRequest& request) { auto& lang = language(request.verb()); return lang.expand(request, inherit_, strict_); } void MarsExpansion::expand(const MarsRequest& request, ExpandCallback& callback) { MarsRequest r = language(request.verb()).expand(request, inherit_, strict_); callback(r); } void MarsExpansion::flatten(const MarsRequest& request, FlattenCallback& callback) { language(request.verb()).flatten(request, callback); } void MarsExpansion::expand(const MarsExpandContext&, const MarsRequest& request, ExpandCallback& callback) { expand(request, callback); } void MarsExpansion::flatten(const MarsExpandContext&, const MarsRequest& request, FlattenCallback& callback) { flatten(request, callback); } //---------------------------------------------------------------------------------------------------------------------- } // namespace metkit::mars metkit-1.16.0/src/metkit/mars/MarsExpansion.h000066400000000000000000000043751513171467200211020ustar00rootroot00000000000000/* * (C) Copyright 1996- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ /// @author Manuel Fuentes /// @author Baudouin Raoult /// @author Tiago Quintino /// @date Sep 96 #ifndef metkit_MarsExpansion_H #define metkit_MarsExpansion_H #include "eckit/memory/NonCopyable.h" #include #include #include #include "metkit/mars/MarsExpandContext.h" #include "metkit/mars/MarsParsedRequest.h" #include "metkit/mars/MarsRequest.h" namespace metkit::mars { class MarsLanguage; //---------------------------------------------------------------------------------------------------------------------- class FlattenCallback { public: virtual ~FlattenCallback(); virtual void operator()(const MarsRequest&) = 0; }; class ExpandCallback { public: virtual ~ExpandCallback(); virtual void operator()(const MarsRequest& request) { this->operator()(DummyContext{}, request); } virtual void operator()(const MarsExpandContext&, const MarsRequest&) = 0; }; //---------------------------------------------------------------------------------------------------------------------- class MarsExpansion : public eckit::NonCopyable { public: MarsExpansion(bool inherit, bool strict = false); ~MarsExpansion(); void reset(); MarsRequest expand(const MarsRequest&); std::vector expand(const std::vector&); void expand(const MarsRequest&, ExpandCallback&); void expand(const MarsExpandContext&, const MarsRequest&, ExpandCallback&); void flatten(const MarsRequest&, FlattenCallback&); void flatten(const MarsExpandContext&, const MarsRequest&, FlattenCallback&); private: MarsLanguage& language(const std::string& verb); std::map languages_; bool inherit_; bool strict_; }; //---------------------------------------------------------------------------------------------------------------------- } // namespace metkit::mars #endif metkit-1.16.0/src/metkit/mars/MarsExpension.h000066400000000000000000000016421513171467200211000ustar00rootroot00000000000000/* * (C) Copyright 1996- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ #ifndef metkit_MarsExpension_H #define metkit_MarsExpension_H #include "metkit/mars/MarsExpansion.h" namespace metkit::mars { //---------------------------------------------------------------------------------------------------------------------- struct [[deprecated("Use MarsExpansion instead")]] MarsExpension : MarsExpansion { using MarsExpansion::MarsExpansion; }; //---------------------------------------------------------------------------------------------------------------------- } // namespace metkit::mars #endif metkit-1.16.0/src/metkit/mars/MarsHandle.cc000066400000000000000000000131121513171467200204540ustar00rootroot00000000000000/* * (C) Copyright 1996- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ #include #include "eckit/config/Resource.h" #include "eckit/log/Bytes.h" #include "eckit/log/Log.h" #include "eckit/serialisation/HandleStream.h" #include "metkit/mars/MarsHandle.h" const unsigned long startCRC = 0xffffffffL; eckit::Reanimator MarsHandle::reanimator_; class MarsHandleStream : public eckit::HandleStream { MarsHandle& handle_; public: MarsHandleStream(MarsHandle& handle) : eckit::HandleStream(handle), handle_(handle) { handle_.streamMode_ = true; } ~MarsHandleStream() { handle_.streamMode_ = false; } }; void MarsHandle::encode(eckit::Stream& s) const { TCPHandle::encode(s); s << clientID_; s << doCRC_; } MarsHandle::MarsHandle(eckit::Stream& s) : TCPHandle(s), length_(0), total_(0), receiving_(false), streamMode_(false), doCRC_(false), crc_(startCRC) { s >> clientID_; if (s.endObjectFound()) { eckit::Log::info() << "Got old metkit without CRC" << std::endl; return; } s >> doCRC_; if (doCRC_) eckit::Log::info() << "Got new metkit with CRC" << std::endl; } MarsHandle::MarsHandle(const std::string& host, int port, unsigned long long clientID) : TCPHandle(host, port), clientID_(clientID), length_(0), total_(0), receiving_(false), streamMode_(false), doCRC_(false), crc_(startCRC) {} MarsHandle::~MarsHandle() {} std::string MarsHandle::title() const { std::ostringstream os; os << "Client["; os << eckit::net::TCPSocket::hostName(host_); os << ":" << port_ << "]"; return os.str(); } std::string MarsHandle::metricsTag() const { std::ostringstream os; os << "client@"; os << eckit::net::TCPSocket::hostName(host_); return os.str(); } eckit::Length MarsHandle::openForRead() { static long size = eckit::Resource("archiveSocketBufferSize", 0); connection_.bufferSize(size); eckit::TCPHandle::openForRead(); MarsHandleStream s(*this); s << clientID_; // Send info s << 'r'; // Send the request s >> length_; // Get the length back eckit::Log::status() << "Receiving " << eckit::Bytes(length_) << std::endl; total_ = 0; receiving_ = true; crc_ = startCRC; return length_; } void MarsHandle::openForWrite(const eckit::Length& length) { eckit::TCPHandle::openForWrite(length); MarsHandleStream s(*this); length_ = length; s << clientID_; // Send info s << 'w'; s << length_; // Send the length eckit::Log::status() << "Sending " << eckit::Bytes(length_) << std::endl; total_ = 0; receiving_ = false; } void MarsHandle::openForAppend(const eckit::Length&) { NOTIMP; } long MarsHandle::read(void* buffer, long length) { if (streamMode_) return TCPHandle::read(buffer, length); long long left = length_ - total_; if (left < length) { length = left; if (length == 0) return 0; } long len = TCPHandle::read(buffer, length); if (doCRC_) updateCRC(buffer, len); total_ += len; return len; } long MarsHandle::write(const void* buffer, long length) { long len = TCPHandle::write(buffer, length); total_ += len; return len; } void MarsHandle::close() { bool gotCRC = false; unsigned long version = 0; unsigned long crc = 0; if (length_ > 0 && total_ != length_) { TCPHandle::close(); eckit::Log::error() << "Recieved/Sent " << total_ << " bytes instead of " << length_ << std::endl; if (eckit::Exception::throwing()) { eckit::Log::error() << "A expection is already active" << std::endl; return; } throw eckit::ShortFile("Bad total in MarsHandle"); } if (receiving_) { crc_ ^= 0xffffffff; length_ = 0; // Try to read CRC try { MarsHandleStream s(*this); s >> version; unsigned long long c; s >> c; crc = ((unsigned long)(c)); gotCRC = true; } catch (std::exception& e) { eckit::Log::warning() << "Cannot read crc: " << e.what() << std::endl; } } if (doCRC_ && gotCRC) { eckit::Log::info() << "Local CRC " << crc_ << ", remote CRC " << crc << std::endl; ASSERT(version == 1); if (crc != crc_) { { FILE* p = popen("mail mab mar", "w"); if (p) { fprintf(p, "CRC error\n"); pclose(p); } } { eckit::PathName lock("~/locks/pause_if_crc_error"); while (lock.exists()) { eckit::Log::status() << "**** CRC ERROR ****" << std::endl; ::sleep(120); } } eckit::TCPHandle::close(); throw eckit::SeriousBug("Invalide checksum"); } } TCPHandle::close(); } eckit::Length MarsHandle::estimate() { return length_; } void MarsHandle::updateCRC(void* buffer, long length) {} const eckit::ClassSpec& MarsHandle::classSpec() { static const eckit::ClassSpec _classSpec = {&TCPHandle::classSpec(), "MarsHandle"}; return _classSpec; } metkit-1.16.0/src/metkit/mars/MarsHandle.h000066400000000000000000000037511513171467200203260ustar00rootroot00000000000000/* * (C) Copyright 1996- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ // File MarsHandle.h // Baudouin Raoult - ECMWF Oct 96 #ifndef MarsHandle_H #define MarsHandle_H #include "eckit/io/Length.h" #include "eckit/io/TCPHandle.h" #include "eckit/serialisation/Stream.h" class MarsHandle : public eckit::TCPHandle { public: // -- Contructors MarsHandle(const std::string& host, int port, unsigned long long); MarsHandle(eckit::Stream&); // -- Destructor ~MarsHandle(); // -- Overridden methods // From eckit::DataHandle virtual eckit::Length openForRead() override; virtual void openForWrite(const eckit::Length&) override; virtual void openForAppend(const eckit::Length&) override; virtual void close() override; virtual long read(void*, long) override; virtual long write(const void*, long) override; virtual eckit::Length estimate() override; virtual std::string title() const override; virtual std::string metricsTag() const override; virtual bool moveable() const override { return true; } // From Streamable virtual void encode(eckit::Stream&) const override; virtual const eckit::ReanimatorBase& reanimator() const override { return reanimator_; } // -- Class methods static const eckit::ClassSpec& classSpec(); private: // -- Members unsigned long long clientID_; eckit::Length length_; eckit::Length total_; bool receiving_; bool streamMode_; bool doCRC_; unsigned long crc_; // -- Methods void updateCRC(void*, long); // -- Class members static eckit::Reanimator reanimator_; friend class MarsHandleStream; }; #endif metkit-1.16.0/src/metkit/mars/MarsLanguage.cc000066400000000000000000000430641513171467200210150ustar00rootroot00000000000000/* * (C) Copyright 1996- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ #include "metkit/mars/MarsLanguage.h" #include #include #include #include "eckit/config/Resource.h" #include "eckit/log/Log.h" #include "eckit/parser/YAMLParser.h" #include "eckit/types/Types.h" #include "eckit/utils/StringTools.h" #include "metkit/config/LibMetkit.h" #include "metkit/hypercube/HyperCube.h" #include "metkit/mars/MarsExpansion.h" #include "metkit/mars/Type.h" #include "metkit/mars/TypesFactory.h" //---------------------------------------------------------------------------------------------------------------------- static pthread_once_t once = PTHREAD_ONCE_INIT; static eckit::Value languages_; static std::vector modifiers_{}; static std::set verbs_; static std::map verbAliases_; static void init() { languages_ = eckit::YAMLParser::decodeFile(metkit::LibMetkit::languageYamlFile()); for (const auto& file : metkit::LibMetkit::modifiersYamlFiles()) { modifiers_.push_back(eckit::YAMLParser::decodeFile(file)); } const eckit::Value verbs = languages_.keys(); for (size_t i = 0; i < verbs.size(); ++i) { verbs_.insert(verbs[i]); eckit::Value lang = languages_[verbs[i]]; if (lang.contains("_aliases")) { eckit::Value aliases = lang["_aliases"]; ASSERT(aliases.isList()); for (size_t j = 0; j < aliases.size(); ++j) { verbAliases_.emplace(aliases[j], verbs[i]); } } } } namespace metkit::mars { //---------------------------------------------------------------------------------------------------------------------- void MarsLanguage::parseModifier(ModifierType typ, std::shared_ptr ctx, size_t maxIndex, const eckit::Value& mod) { eckit::Value keys; if (typ == ModifierType::UNSET) { ASSERT(mod.isList()); keys = mod; } else { ASSERT(mod.isMap()); keys = mod.keys(); } for (size_t j = 0; j < keys.size(); ++j) { std::string key = keys[j]; auto it = types_.find(key); if (it != types_.end()) { ASSERT(!isData(key) || maxIndex <= metkit::hypercube::AxisOrder::instance().index(key)); if (typ == ModifierType::UNSET) { it->second->unset(ctx); } else { eckit::Value vv = mod[key]; std::vector vals; if (vv.isList()) { for (size_t k = 0; k < vv.size(); ++k) { vals.push_back(vv[k]); } } else { vals.push_back(vv); } if (typ == ModifierType::DEFAULT) it->second->defaults(ctx, vals); else if (typ == ModifierType::SET) it->second->set(ctx, vals); } } } } MarsLanguage::MarsLanguage(const std::string& verb) : verb_(verb) { pthread_once(&once, init); eckit::Value lang = languages_[verb]; eckit::Value params = lang.keys(); eckit::Value options = lang["_options"]; for (size_t i = 0; i < params.size(); ++i) { std::string keyword = params[i]; eckit::Value settings = lang[keyword]; if (keyword[0] == '_') { continue; } ASSERT(types_.find(keyword) == types_.end()); if (options.contains(keyword)) { eckit::ValueMap m = options[keyword]; for (auto j = m.begin(); j != m.end(); ++j) { settings[(*j).first] = (*j).second; } } auto [it, success] = types_.emplace(keyword, TypesFactory::build(keyword, settings)); it->second->attach(); keywords_.push_back(keyword); std::optional aliases; if (settings.contains("aliases")) { aliases = settings["aliases"]; } if (settings.contains("category") && settings["category"] == "data") { dataKeywords_.insert(keyword); if (aliases) { for (size_t j = 0; j < aliases->size(); ++j) { dataKeywords_.insert((*aliases)[j]); } } } if (settings.contains("category") && settings["category"] == "postproc") { postProcKeywords_.insert(keyword); if (aliases) { for (auto j = 0; j < aliases->size(); ++j) { postProcKeywords_.insert((*aliases)[j]); } } } if (settings.contains("category") && settings["category"] == "sink") { sinkKeywords_.insert(keyword); if (aliases) { for (auto j = 0; j < aliases->size(); ++j) { sinkKeywords_.insert((*aliases)[j]); } } } if (aliases) { for (size_t j = 0; j < aliases->size(); ++j) { aliases_[(*aliases)[j]] = keyword; keywords_.push_back((*aliases)[j]); } } } // load modifiers and associate to types for (const auto& modifierFile : modifiers_) { ASSERT(modifierFile.isList()); for (size_t i = 0; i < modifierFile.size(); ++i) { eckit::Value mod = modifierFile[i]; ASSERT(mod.isMap()); ASSERT(mod.contains("context")); std::shared_ptr ctx = Context::parseContext(mod["context"]); size_t maxIndex = ctx->maxAxisIndex(); if (mod.contains("defaults")) { parseModifier(ModifierType::DEFAULT, ctx, maxIndex, mod["defaults"]); } if (mod.contains("set")) { parseModifier(ModifierType::SET, ctx, maxIndex, mod["set"]); } if (mod.contains("unset")) { parseModifier(ModifierType::UNSET, ctx, maxIndex, mod["unset"]); } } } if (lang.contains("_clear_defaults")) { const auto& keywords = lang["_clear_defaults"]; for (auto i = 0; i < keywords.size(); ++i) { if (auto iter = types_.find(keywords[i]); iter != types_.end()) { iter->second->clearDefaults(); } } } for (const std::string& a : hypercube::AxisOrder::instance().axes()) { Type* t = nullptr; auto it = types_.find(a); if (it != types_.end()) { t = it->second; } typesByAxisOrder_.emplace_back(a, t); } for (auto& [k, t] : types_) { if (dataKeywords_.find(k) == dataKeywords_.end()) { typesByAxisOrder_.emplace_back(k, t); } } } bool MarsLanguage::isData(const std::string& keyword) const { return (dataKeywords_.find(keyword) != dataKeywords_.end()); } bool MarsLanguage::isPostProc(const std::string& keyword) const { return (postProcKeywords_.find(keyword) != postProcKeywords_.end()); } bool MarsLanguage::isSink(const std::string& keyword) const { return (sinkKeywords_.find(keyword) != sinkKeywords_.end()); } const std::set& MarsLanguage::sinkKeywords() const { return sinkKeywords_; } MarsLanguage::~MarsLanguage() { for (auto& [k, t] : types_) { t->detach(); } } eckit::PathName MarsLanguage::languageYamlFile() { return metkit::LibMetkit::languageYamlFile(); } void MarsLanguage::reset() { for (auto& [k, t] : types_) { t->reset(); } } eckit::Value MarsLanguage::jsonFile(const std::string& name) { // TODO: cache eckit::PathName path = metkit::LibMetkit::configFile(name); LOG_DEBUG_LIB(LibMetkit) << "MarsLanguage loading jsonFile " << path << std::endl; std::ifstream in(path.asString().c_str()); if (!in) { throw eckit::CantOpenFile(path); } eckit::YAMLParser parser(in); return parser.parse(); } static bool isnumeric(const std::string& s) { for (size_t i = 0; i < s.length(); i++) { if (!::isdigit(s[i])) { return false; } } return s.length() > 0; } std::string MarsLanguage::bestMatch(const std::string& name, const std::vector& values, bool fail, bool quiet, bool fullMatch, const std::map& aliases) { size_t score = (fullMatch ? name.length() : 1); std::vector best; for (size_t i = 0; i < values.size(); ++i) { const std::string& value = values[i]; size_t len = std::min(name.length(), value.length()); size_t s = 0; // Prefix comparison, break if there is a difference for (size_t j = 0; j < len; ++j) { if (::tolower(name[j]) == ::tolower(value[j])) { s++; } else { break; } } // if value and name are the same (in lowercase), look up aliases and return the alias // otherwise return the value (which is name) if (s == value.length() && s == name.length()) { if (aliases.find(value) != aliases.end()) { return aliases.find(value)->second; } return value; } // If fullmatch == true: // only option is s==score, otherwise the break above would have triggered // so best is only filled with exact matches // If fullmatch == false: // score keeps track of the best value found, if a better value (in terms of matching prefixes) // is found, clear the best vector and push the new best. If all matches are equally good, keep them in the best // vector if (s >= score) { if (s > score) { best.clear(); } best.push_back(value); score = s; } } if (!quiet && best.size() > 0) { std::cerr << "Matching '" << name << "' with " << best << std::endl; } static bool strict = eckit::Resource("$METKIT_LANGUAGE_STRICT_MODE", true); if (best.size() == 1) { // If the best entry is a number or not name (why is this even needed) if (isnumeric(best[0]) && (best[0] != name)) { best.clear(); } else { if (strict) { if (best[0] != name) { std::ostringstream oss; oss << "Cannot match [" << name << "] in " << values; throw eckit::UserError(oss.str()); } } if (aliases.find(best[0]) != aliases.end()) { return aliases.find(best[0])->second; } return best[0]; } } // In case the match is empty, return or fail, depending on the fail flag static std::string empty; if (best.empty()) { if (!fail) { return empty; } std::ostringstream oss; oss << "Cannot match [" << name << "] in " << values; throw eckit::UserError(oss.str()); } // Check the existing aliases for mappings of the matches to the canonical parameter name // A set is used to de-duplicate the findings std::set names; for (std::vector::const_iterator j = best.begin(); j != best.end(); ++j) { const auto k = aliases.find(*j); if (k == aliases.end()) { names.insert(*j); } else { names.insert((*k).second); } } // If there is only on match return the given one if (names.size() == 1) { if (aliases.find(best[0]) != aliases.end()) { return aliases.find(best[0])->second; } return best[0]; } // Otherwise there is an ambiguity and we want to return or fail (depending on the fail flag) if (!fail) { return empty; } std::ostringstream oss; oss << "Ambiguous value '" << name << "' could be"; for (std::vector::const_iterator j = best.begin(); j != best.end(); ++j) { auto k = aliases.find(*j); if (k == aliases.end()) { oss << " '" << *j << "'"; } else { oss << " '" << *j << "' ("; oss << (*k).second; oss << ")"; } } throw eckit::UserError(oss.str()); } std::string MarsLanguage::expandVerb(const std::string& verb) { pthread_once(&once, init); std::string v = eckit::StringTools::lower(verb); auto vv = verbs_.find(v); if (vv != verbs_.end()) { return v; } auto aa = verbAliases_.find(v); if (aa != verbAliases_.end()) { return aa->second; } std::ostringstream oss; oss << "Verb " << v << " is not supported"; throw eckit::UserError(oss.str()); } class TypeHidden : public Type { bool flatten() const override { return false; } void print(std::ostream& out) const override { out << "TypeHidden"; } bool expand(std::string&, const MarsRequest&) const override { return true; } public: TypeHidden() : Type("hidden", eckit::Value()) { attach(); } }; Type* MarsLanguage::type(const std::string& name) const { auto k = types_.find(name); if (k == types_.end()) { if (name[0] == '_') { static TypeHidden hidden; return &hidden; } throw eckit::SeriousBug("Cannot find a type for '" + name + "'"); } return k->second; } MarsRequest MarsLanguage::expand(const MarsRequest& r, bool inherit, bool strict) { MarsRequest result(verb_); try { std::vector> sortedParams; std::map paramSet; std::vector params; for (const auto& PP : r.params()) { auto c = cache_.find(PP); if (c != cache_.end()) { paramSet.emplace((*c).second, PP); } else { std::string p = eckit::StringTools::lower(PP); paramSet.emplace(cache_[p] = bestMatch(p, keywords_, true, false, true, aliases_), PP); } } { // sort the parameters, following the AxisOrder for (const auto& k : metkit::hypercube::AxisOrder::instance().axes()) { auto it = paramSet.find(k); if (it != paramSet.end()) { sortedParams.emplace_back(k, it->second); paramSet.erase(it); } } for (const auto& [k, PP] : paramSet) { sortedParams.emplace_back(k, PP); } } for (const auto& [p, PP] : sortedParams) { std::vector values = r.values(PP); if (values.size() == 1) { const std::string& s = eckit::StringTools::lower(values[0]); if (s == "off") { result.unsetValues(p); type(p)->reset(); continue; } if (s == "all" && type(p)->multiple()) { result.setValue(p, "all"); continue; } } auto t = type(p); t->expand(values, result); result.setValuesTyped(t, values); t->check(values); } if (inherit) { for (const auto& [k, t] : typesByAxisOrder_) { if (t != nullptr && result.countValues(k) == 0) { t->setDefaults(result); } } result.getParams(params); for (std::vector::const_iterator k = params.begin(); k != params.end(); ++k) { type(*k)->setInheritance(result.values(*k)); } } result.getParams(params); for (std::vector::const_iterator k = params.begin(); k != params.end(); ++k) { type(*k)->pass2(result); } for (const auto& [k, t] : typesByAxisOrder_) { if (t != nullptr) t->finalise(result, strict); } } catch (std::exception& e) { std::ostringstream oss; oss << e.what() << " request=" << r << ", expanded=" << result; throw eckit::UserError(oss.str()); } return result; } const std::string& MarsLanguage::verb() const { return verb_; } void MarsLanguage::flatten(const MarsRequest& request, const std::vector& params, size_t i, MarsRequest& result, FlattenCallback& callback) { if (i == params.size()) { callback(result); return; } const std::string& param = params[i]; Type* t = type(param); if (!t->flatten()) { flatten(request, params, i + 1, result, callback); return; } const std::vector& values = t->flattenValues(request); for (std::vector::const_iterator j = values.begin(); j != values.end(); ++j) { result.setValue(param, *j); flatten(request, params, i + 1, result, callback); } } void MarsLanguage::flatten(const MarsRequest& request, FlattenCallback& callback) { std::vector params; request.getParams(params); MarsRequest result(request); flatten(request, params, 0, result, callback); } //---------------------------------------------------------------------------------------------------------------------- } // namespace metkit::mars metkit-1.16.0/src/metkit/mars/MarsLanguage.h000066400000000000000000000056231513171467200206560ustar00rootroot00000000000000/* * (C) Copyright 1996- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ /// @author Manuel Fuentes /// @author Baudouin Raoult /// @author Tiago Quintino /// @date Sep 96 #pragma once #include #include #include #include #include #include "eckit/memory/NonCopyable.h" #include "metkit/mars/MarsRequest.h" namespace metkit::mars { class Context; class FlattenCallback; class Type; //---------------------------------------------------------------------------------------------------------------------- enum class ModifierType { DEFAULT, SET, UNSET }; //---------------------------------------------------------------------------------------------------------------------- class MarsLanguage : private eckit::NonCopyable { public: // methods MarsLanguage(const std::string& verb); ~MarsLanguage(); MarsRequest expand(const MarsRequest& r, bool inherit, bool strict); void reset(); const std::string& verb() const; void flatten(const MarsRequest& request, FlattenCallback& callback); static eckit::PathName languageYamlFile(); Type* type(const std::string& name) const; bool isData(const std::string& keyword) const; bool isPostProc(const std::string& keyword) const; bool isSink(const std::string& keyword) const; const std::set& sinkKeywords() const; public: // class methods static std::string expandVerb(const std::string& verb); static std::string bestMatch(const std::string& name, const std::vector& values, bool fail, bool quiet, bool fullMatch, const std::map& aliases = {}); static eckit::Value jsonFile(const std::string& name); private: // methods void flatten(const MarsRequest& request, const std::vector& params, size_t i, MarsRequest& result, FlattenCallback& callback); void parseModifier(ModifierType typ, std::shared_ptr ctx, size_t maxIndex, const eckit::Value& mod); private: // members std::string verb_; std::map types_; std::set dataKeywords_; std::set sinkKeywords_; std::set postProcKeywords_; std::vector> typesByAxisOrder_; std::vector keywords_; std::map aliases_; mutable std::map cache_; }; //---------------------------------------------------------------------------------------------------------------------- } // namespace metkit::mars metkit-1.16.0/src/metkit/mars/MarsLocation.cc000066400000000000000000000047061513171467200210420ustar00rootroot00000000000000/* * (C) Copyright 1996- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ #include #include #include "eckit/config/Configuration.h" #include "eckit/config/LocalConfiguration.h" #include "eckit/config/Resource.h" #include "eckit/log/JSON.h" #include "eckit/log/Log.h" #include "eckit/utils/MD5.h" #include "eckit/utils/StringTools.h" #include "eckit/utils/Translator.h" #include "metkit/mars/MarsLocation.h" namespace metkit { namespace mars { //---------------------------------------------------------------------------------------------------------------------- MarsLocation::MarsLocation(const MarsRequest& r, const std::string& hostname, int port) : request_(r), hostname_(hostname), port_(port) {} MarsLocation::MarsLocation(eckit::Stream& s) : request_(s) { s >> hostname_; s >> port_; NOTIMP; // FIXME: added this constructor just to get develop branches to compile } MarsLocation::MarsLocation(const eckit::Configuration& c) : request_(c.getString("request")), hostname_(c.getString("server")), port_(c.getInt("port")) {} MarsLocation::~MarsLocation() {} metkit::mars::MarsLocation::operator eckit::Value() const { eckit::Value dict = eckit::Value::makeMap(); dict["request"] = request_; dict["server"] = hostname_; dict["port"] = port_; return dict; } void MarsLocation::encode(eckit::Stream& s) const { s << request_; s << hostname_; s << port_; } const MarsRequest& MarsLocation::request() const { return request_; } std::string MarsLocation::hostname() const { return hostname_; } int MarsLocation::port() const { return port_; } void MarsLocation::print(std::ostream& s) const { s << request_ << ',' << std::endl; s << "hostname=" << hostname_ << ',' << std::endl; s << "port=" << port_ << std::endl; } void MarsLocation::json(eckit::JSON& s) const { s.startObject(); s << "request" << request_; s << "hostname" << hostname_; s << "port" << port_; s.endObject(); } //---------------------------------------------------------------------------------------------------------------------- } // namespace mars } // namespace metkit metkit-1.16.0/src/metkit/mars/MarsLocation.h000066400000000000000000000046621513171467200207050ustar00rootroot00000000000000/* * (C) Copyright 1996- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ /// @author Tiago Quintino /// @date Dec 2015 #ifndef metkit_MarsLocation_H #define metkit_MarsLocation_H #include "eckit/config/Configuration.h" #include "metkit/mars/MarsRequest.h" namespace eckit { class JSON; class Stream; } // namespace eckit namespace metkit { namespace mars { //---------------------------------------------------------------------------------------------------------------------- /// MarsLocation represents a MarsRequest associated with the hostname and port. /// From this location, the data can be directly retrieved without going through a queueing system. /// It assumes all the data identified by the request can be got from the same location. /// This is useful to identify and retrieve data directly from memory. /// /// If we consider that a MarsRequest is analogue to a URI, then a MarsLocation is an analogue to a URL class MarsLocation { public: // methods // - Constructors MarsLocation(const MarsRequest& r, const std::string& hostname, int port); MarsLocation(eckit::Stream&); MarsLocation(const eckit::Configuration&); // -- Destructor ~MarsLocation(); // -- Operators operator eckit::Value() const; void json(eckit::JSON&) const; const MarsRequest& request() const; std::string hostname() const; int port() const; private: // members MarsRequest request_; std::string hostname_; int port_; private: // methods void print(std::ostream&) const; void encode(eckit::Stream&) const; // -- Class members friend std::ostream& operator<<(std::ostream& s, const MarsLocation& r) { r.print(s); return s; } friend eckit::JSON& operator<<(eckit::JSON& s, const MarsLocation& r) { r.json(s); return s; } friend eckit::Stream& operator<<(eckit::Stream& s, const MarsLocation& r) { r.encode(s); return s; } }; //---------------------------------------------------------------------------------------------------------------------- } // namespace mars } // namespace metkit #endif metkit-1.16.0/src/metkit/mars/MarsParsedRequest.cc000066400000000000000000000013061513171467200220520ustar00rootroot00000000000000/* * (C) Copyright 1996- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ #include "metkit/mars/MarsParsedRequest.h" namespace metkit::mars { MarsParsedRequest::MarsParsedRequest(const std::string& verb, size_t line) : MarsRequest(verb), line_(line) {} void MarsParsedRequest::info(std::ostream& out) const { out << " Request starting line " << line_; } } // namespace metkit::mars metkit-1.16.0/src/metkit/mars/MarsParsedRequest.h000066400000000000000000000022771513171467200217240ustar00rootroot00000000000000/* * (C) Copyright 1996- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ /// @author Manuel Fuentes /// @author Baudouin Raoult /// @author Tiago Quintino /// @date Sep 96 #pragma once #include "metkit/mars/MarsRequest.h" namespace metkit::mars { //---------------------------------------------------------------------------------------------------------------------- class MarsParsedRequest : public MarsRequest { public: MarsParsedRequest(const std::string& verb, size_t line); virtual ~MarsParsedRequest() = default; virtual void info(std::ostream&) const; friend std::ostream& operator<<(std::ostream& s, const MarsParsedRequest& r) { r.info(s); return s; } private: std::size_t line_; }; //---------------------------------------------------------------------------------------------------------------------- } // namespace metkit::mars metkit-1.16.0/src/metkit/mars/MarsParser.cc000066400000000000000000000112111513171467200205130ustar00rootroot00000000000000/* * (C) Copyright 1996- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ /// @file MarsParser.h /// @author Baudouin Raoult /// @author Tiago Quintino /// @date Jun 2012 #include "metkit/mars/MarsParser.h" #include "metkit/mars/MarsExpandContext.h" namespace metkit::mars { //---------------------------------------------------------------------------------------------------------------------- std::string MarsParser::parseString(char quote) { consume(quote); std::string s; for (;;) { char c = next(true); if (c == '\\') { c = next(true); switch (c) { case '"': s += '"'; break; case '\'': s += '\''; break; case '\\': s += '\\'; break; case '/': s += '/'; break; case 'b': s += '\b'; break; case 'f': s += '\f'; break; case 'n': s += '\n'; break; case 'r': s += '\r'; break; case 't': s += '\t'; break; case 'u': throw StreamParser::Error(std::string("JSONTokenizer::parseString \\uXXXX format not supported")); default: throw StreamParser::Error(std::string("JSONTokenizer::parseString invalid \\ char '") + c + "'"); } } else { if (c == quote) { return s; // void(s); } s += c; } } } static bool inindent(char c) { return isalnum(c) || c == '_' || c == ':' || c == '-' || c == '.' || c == '@'; } void MarsParser::quoted(std::ostream& out, const std::string& value) { char quote = 0; for (std::string::const_iterator j = value.begin(); j != value.end(); ++j) { if (!inindent(*j)) { quote = '"'; break; } } if (quote) { out << quote << value << quote; } else { out << value; } } std::string MarsParser::parseIndents() { std::ostringstream oss; oss << parseIndent(); for (;;) { char c = peek(true); while (c == ' ') { next(true); c = peek(true); } if (!inindent(c)) { break; } oss << " " << parseIndent(); } return oss.str(); } std::string MarsParser::parseValue() { char c = peek(); if (c == '\"' || c == '\'') { return parseString(c); } return parseIndents(); } std::vector MarsParser::parseValues() { std::vector v(1, parseValue()); char c = peek(); while (c == '/') { consume('/'); v.push_back(parseValue()); c = peek(); } return v; } std::string MarsParser::parseIndent() { char c = peek(); std::string s; while (inindent(c)) { s += next(true); c = peek(true); } return s; } std::string MarsParser::parseVerb() { char c = peek(); if (!isalpha(c) && c != '_') { throw StreamParser::Error(std::string("MarsParser::parseVerb invalid char '") + c + "'", line_ + 1); } return parseIndent(); } MarsParsedRequest MarsParser::parseRequest() { MarsParsedRequest r(parseVerb(), line_ + 1); char c = peek(); while (c == ',') { consume(','); std::string key = parseIndents(); consume('='); r.values(key, parseValues()); c = peek(); } if (c == '.') { consume('.'); } return r; } MarsParser::MarsParser(std::istream& in) : StreamParser(in, true, "#") {} std::vector MarsParser::parse() { std::vector result; while (peek() != 0) { result.push_back(parseRequest()); } return result; } void MarsParser::parse(MarsParserCallback& cb) { while (peek() != 0) { auto r = parseRequest(); cb(DummyContext{}, r); } } //---------------------------------------------------------------------------------------------------------------------- } // namespace metkit::mars metkit-1.16.0/src/metkit/mars/MarsParser.h000066400000000000000000000033611513171467200203640ustar00rootroot00000000000000/* * (C) Copyright 1996- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ /// @author Baudouin Raoult /// @date Jun 2012 #pragma once #include "eckit/parser/StreamParser.h" #include "eckit/types/Types.h" #include "metkit/mars/MarsParsedRequest.h" namespace metkit::mars { class MarsExpandContext; class MarsRequest; //---------------------------------------------------------------------------------------------------------------------- class MarsParserCallback { public: virtual void operator()(const MarsExpandContext&, const MarsRequest&) = 0; protected: virtual ~MarsParserCallback() = default; }; //---------------------------------------------------------------------------------------------------------------------- class MarsParser : public eckit::StreamParser { public: // methods MarsParser(std::istream& in); std::vector parse(); void parse(MarsParserCallback& cb); static void quoted(std::ostream& out, const std::string& value); private: // methods MarsParsedRequest parseRequest(); std::string parseVerb(); std::string parseKeyword(); std::vector parseValues(); std::string parseValue(); std::string parseIndent(); std::string parseIndents(); std::string parseString(char c); }; //---------------------------------------------------------------------------------------------------------------------- } // namespace metkit::mars metkit-1.16.0/src/metkit/mars/MarsRequest.cc000066400000000000000000000363321513171467200207220ustar00rootroot00000000000000/* * (C) Copyright 1996- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ #include "eckit/log/JSON.h" #include "eckit/log/Log.h" #include "eckit/types/Types.h" #include "eckit/utils/MD5.h" #include "eckit/utils/StringTools.h" #include "eckit/message/Message.h" #include "metkit/config/LibMetkit.h" #include "metkit/mars/MarsExpansion.h" #include "metkit/mars/MarsParser.h" #include "metkit/mars/MarsRequest.h" #include "metkit/mars/ParamID.h" #include "metkit/mars/TypeAny.h" namespace metkit { namespace mars { //---------------------------------------------------------------------------------------------------------------------- MarsRequest::MarsRequest() {} MarsRequest::MarsRequest(const std::string& s) : verb_(s) {} MarsRequest::MarsRequest(const std::string& s, const std::map& values) : verb_(s) { for (auto j = values.begin(); j != values.end(); ++j) { const std::string& param = (*j).first; const std::string& value = (*j).second; params_.push_back(Parameter(std::vector(1, value), new TypeAny(param))); } } MarsRequest::MarsRequest(const std::string& s, const eckit::Value& values) : verb_(s) { eckit::ValueMap m = values; for (auto j = m.begin(); j != m.end(); ++j) { const std::string& param = (*j).first; const eckit::Value& value = (*j).second; if (value.isList()) { std::vector vals; eckit::fromValue(vals, value); params_.push_back(Parameter(vals, new TypeAny(param))); } else { params_.push_back(Parameter(std::vector(1, value), new TypeAny(param))); } } } MarsRequest::MarsRequest(const eckit::message::Message& message) : verb_("message") { eckit::message::StringSetter setter(*this); message.getMetadata(setter); } MarsRequest::MarsRequest(eckit::Stream& s, bool lowercase) { int size; s >> verb_; if (lowercase) verb_ = eckit::StringTools::lower(verb_); s >> size; for (int i = 0; i < size; i++) { std::string param; int count; s >> param; if (lowercase) param = eckit::StringTools::lower(param); s >> count; std::vector v; v.reserve(count); for (int k = 0; k < count; k++) { std::string value; s >> value; v.push_back(value); } params_.push_back(Parameter(v, new TypeAny(param))); } } void MarsRequest::encode(eckit::Stream& s) const { s << verb_; int size = params_.size(); s << size; for (std::list::const_iterator i = params_.begin(); i != params_.end(); ++i) { s << (*i).name(); const std::vector& v = (*i).values(); int size = v.size(); // For backward compatibility s << size; for (std::vector::const_iterator k = v.begin(); k != v.end(); ++k) { s << *k; } } } bool MarsRequest::empty() const { return params_.empty(); } void MarsRequest::print(std::ostream& s) const { dump(s, "", "", true); } void MarsRequest::dump(std::ostream& s, const char* cr, const char* tab, bool verb) const { std::list::const_iterator begin = params_.begin(); std::list::const_iterator end = params_.end(); if (verb) { s << verb_ << ','; } std::string separator = ""; if (begin != end) { s << separator << cr << tab; separator = ","; int a = 0; for (std::list::const_iterator i = begin; i != end; ++i) { if (a++) { s << ','; s << cr << tab; } int b = 0; s << (*i).name() // << "." << (*i).second.type() << "="; const std::vector& v = (*i).values(); for (std::vector::const_iterator k = v.begin(); k != v.end(); ++k) { if (b++) { s << '/'; } MarsParser::quoted(s, *k); } // s << " {" << (*i).type().category() << "}"; } } s << cr << cr; } void MarsRequest::json(eckit::JSON& s, bool array) const { s.startObject(); // s << "_verb" << verb_; std::list::const_iterator begin = params_.begin(); std::list::const_iterator end = params_.end(); for (std::list::const_iterator i = begin; i != end; ++i) { s << (*i).name(); const std::vector& v = (*i).values(); bool list = v.size() != 1 || (array && (*i).type().multiple()); if (list) { s.startList(); } for (std::vector::const_iterator k = v.begin(); k != v.end(); ++k) { s << (*k); } if (list) { s.endList(); } } s.endObject(); } void MarsRequest::md5(eckit::MD5& md5) const { std::ostringstream oss; oss << *this; md5.add(oss.str()); } void MarsRequest::unsetValues(const std::string& name) { std::list::iterator i = find(name); if (i != params_.end()) { params_.erase(i); } } void MarsRequest::setValuesTyped(Type* type, const std::vector& values) { std::list::iterator i = find(type->name()); if (i != params_.end()) { (*i) = Parameter(values, type); } else { params_.push_back(Parameter(values, type)); } } bool MarsRequest::filter(const MarsRequest& filter) { for (std::list::iterator i = params_.begin(); i != params_.end(); ++i) { if ((*i).name() == "date") { std::list::const_iterator j = filter.find("day"); if (j != filter.params_.end()) { if (!(*i).filter("day", (*j).values())) { return false; } } } std::list::const_iterator j = filter.find((*i).name()); if (j == filter.params_.end()) { continue; } if (!(*i).filter((*j).values())) { return false; } } return true; } bool MarsRequest::matches(const MarsRequest& matches) const { std::vector params = matches.params(); for (std::vector::const_iterator j = params.begin(); j != params.end(); ++j) { std::list::const_iterator k = find(*j); if (k == params_.end()) { return false; } if (!(*k).matches(matches.values(*j))) { return false; } } return true; } void MarsRequest::values(const std::string& name, const std::vector& v) { std::list::iterator i = find(name); if (i != params_.end()) { (*i).values(v); } else { params_.push_back(Parameter(v, new TypeAny(name))); } } size_t MarsRequest::countValues(const std::string& name) const { std::list::const_iterator i = find(name); if (i != params_.end()) { return (*i).values().size(); } return 0; } bool MarsRequest::has(const std::string& name) const { return find(name) != params_.end(); } bool MarsRequest::is(const std::string& name, const std::string& value) const { std::list::const_iterator i = find(name); if (i != params_.end()) { const std::vector& v = (*i).values(); return v.size() == 1 && v[0] == value; } return false; } const std::vector& MarsRequest::values(const std::string& name, bool emptyOk) const { std::list::const_iterator i = find(name); if (i == params_.end()) { if (emptyOk) { static std::vector empty; return empty; } std::ostringstream oss; oss << "No parameter called '" << name << "' in request " << *this; throw eckit::UserError(oss.str()); } return (*i).values(); } std::optional>> MarsRequest::get( const std::string& keyword) const { std::list::const_iterator i = find(keyword); if (i == params_.end()) { return std::nullopt; } return std::cref((*i).values()); } const std::string& MarsRequest::operator[](const std::string& name) const { std::list::const_iterator i = find(name); if (i == params_.end()) { std::ostringstream oss; oss << "Parameter '" << name << "' is undefined"; throw eckit::UserError(oss.str()); } const std::vector& c = (*i).values(); if (c.size() > 1) { std::ostringstream oss; oss << "Parameter '" << name << "' has more than one value"; throw eckit::UserError(oss.str()); } return c[0]; } void MarsRequest::getParams(std::vector& p) const { p.clear(); for (std::list::const_iterator i = params_.begin(); i != params_.end(); ++i) { p.push_back((*i).name()); } } size_t MarsRequest::count() const { size_t result = 1; const std::set& paramIdsSingleLevel = ParamID::getMlParamsSingleLevel(); bool ml = false; size_t levels = 1; size_t params = 0; size_t paramsSingleLevel = 0; for (const auto& p : params_) { if (p.values().size() == 1 && (p.values().at(0) == "all" || p.values().at(0) == "any")) { return 0; } if (p.name() == "levelist") { levels = p.values().size(); } else { if (p.name() == "param") { for (const auto& v : p.values()) { paramsSingleLevel += paramIdsSingleLevel.count(v); } params = p.values().size() - paramsSingleLevel; } else { if (p.name() == "levtype") { ml = std::find(p.values().begin(), p.values().end(), "ml") != p.values().end(); } result *= p.count(); } } } if ((params + paramsSingleLevel) > 0) { if (ml) { result *= (levels * params + paramsSingleLevel); } else { result *= (levels * (params + paramsSingleLevel)); } } return result; } std::vector MarsRequest::params() const { std::vector p; getParams(p); return p; } MarsRequest::operator eckit::Value() const { NOTIMP; } // recursively expand along keys in expvalues void expand_along_keys(const MarsRequest& prototype, const std::vector>>& expvalues, std::vector& requests, size_t i) { if (i == expvalues.size()) { requests.push_back(prototype); return; } const std::string& key = expvalues[i].first; const std::vector& values = expvalues[i].second; MarsRequest req(prototype); for (auto& value : values) { req.setValue(key, value); expand_along_keys(req, expvalues, requests, i + 1); } } std::vector MarsRequest::split(const std::vector& keys) const { size_t n = 1; LOG_DEBUG_LIB(LibMetkit) << "Splitting request with keys" << keys << std::endl; std::vector>> expvalues; for (auto& key : keys) { std::vector v = values(key, true); // ok to be empty LOG_DEBUG_LIB(LibMetkit) << "splitting along key " << key << " n values " << v.size() << " values " << v << std::endl; if (v.empty()) continue; n *= v.size(); expvalues.emplace_back(std::make_pair(key, v)); } std::vector requests; requests.reserve(n); if (n == 1) { requests.push_back(*this); return requests; } expand_along_keys(*this, expvalues, requests, 0); return requests; } std::vector MarsRequest::split(const std::string& key) const { std::vector keys = {key}; return split(keys); } void MarsRequest::merge(const MarsRequest& other) { for (auto& param : params_) { LOG_DEBUG_LIB(LibMetkit) << "Merging parameter " << param << std::endl; auto it = other.find(param.name()); if (it != other.params_.end()) param.merge(*it); } } MarsRequest MarsRequest::subset(const std::set& keys) const { MarsRequest req(verb_); for (std::list::const_iterator it = params_.begin(); it != params_.end(); ++it) { if (keys.find(it->name()) != keys.end()) { req.params_.push_back(*it); } } return req; } MarsRequest MarsRequest::extract(const std::string& category) const { MarsRequest req(verb_); for (std::list::const_iterator it = params_.begin(); it != params_.end(); ++it) { if (it->type().category() == category) { req.params_.push_back(*it); } } return req; } void MarsRequest::verb(const std::string& verb) { verb_ = verb; } bool MarsRequest::operator<(const MarsRequest& other) const { if (verb_ != other.verb_) { return verb_ < other.verb_; } return params_ < other.params_; } void MarsRequest::setValue(const std::string& name, const char* value) { std::string v(value); setValue(name, v); } const std::string& MarsRequest::verb() const { return verb_; } std::list::const_iterator MarsRequest::find(const std::string& name) const { for (std::list::const_iterator i = params_.begin(); i != params_.end(); ++i) { if ((*i).name() == name) { return i; } } return params_.end(); } std::list::iterator MarsRequest::find(const std::string& name) { for (std::list::iterator i = params_.begin(); i != params_.end(); ++i) { if ((*i).name() == name) { return i; } } return params_.end(); } void MarsRequest::erase(const std::string& name) { auto it = find(name); if (it != params_.end()) { params_.erase(it); } } std::string MarsRequest::asString() const { std::ostringstream oss; oss << *this; return oss.str(); } //---------------------------------------------------------------------------------------------------------------------- std::vector MarsRequest::parse(std::istream& in, bool strict) { MarsParser parser(in); MarsExpansion expand(true, strict); return expand.expand(parser.parse()); } MarsRequest MarsRequest::parse(const std::string& s, bool strict) { std::istringstream in(s); std::vector v = parse(in, strict); ASSERT(v.size() == 1); return v[0]; } //---------------------------------------------------------------------------------------------------------------------- } // namespace mars } // namespace metkit metkit-1.16.0/src/metkit/mars/MarsRequest.h000066400000000000000000000130451513171467200205600ustar00rootroot00000000000000/* * (C) Copyright 1996- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ /// @author Manuel Fuentes /// @author Baudouin Raoult /// @author Tiago Quintino /// @date Sep 96 #ifndef metkit_MarsRequest_H #define metkit_MarsRequest_H #include #include "eckit/value/Value.h" #include "metkit/mars/Parameter.h" namespace eckit { class MD5; namespace message { class Message; } } // namespace eckit struct metkit_marsrequest_t; namespace metkit::mars { class Type; class MarsRequest; //---------------------------------------------------------------------------------------------------------------------- class MarsRequest { public: // methods MarsRequest(); explicit MarsRequest(const std::string&); explicit MarsRequest(eckit::Stream&, bool lowercase = false); MarsRequest(const std::string&, const std::map&); MarsRequest(const std::string&, const eckit::Value&); explicit MarsRequest(const eckit::message::Message&); ~MarsRequest() = default; bool operator<(const MarsRequest& other) const; // eckit::Value& operator[](const std::string&); const std::string& operator[](const std::string&) const; operator eckit::Value() const; const std::string& verb() const; size_t countValues(const std::string&) const; bool has(const std::string&) const; bool is(const std::string& param, const std::string& value) const; const std::vector& values(const std::string&, bool emptyOk = false) const; // Returns reference to values or nullopt if not found std::optional>> get(const std::string& keyword) const; template size_t getValues(const std::string& name, std::vector& v, bool emptyOk = false) const; void getParams(std::vector&) const; std::vector params() const; std::list& parameters() { return params_; } const std::list& parameters() const { return params_; } void verb(const std::string&); void values(const std::string&, const std::vector&); template void setValue(const std::string& name, const T& value); void setValue(const std::string& name, const char* value); void unsetValues(const std::string&); /// Splits a MARS request into multiple requests along the provided key std::vector split(const std::string& keys) const; /// Splits a MARS request into multiple requests along the indicated keys std::vector split(const std::vector& keys) const; /// Merges one MarsRequest into another /// @todo Improve performance -- uses O(N^2) search / merge in std::list's void merge(const MarsRequest& other); /// Create a new MarsRequest from this one with only the given set of keys MarsRequest subset(const std::set&) const; void json(eckit::JSON&, bool array = false) const; void md5(eckit::MD5&) const; void dump(std::ostream&, const char* cr = "\n", const char* tab = "\t", bool verb = true) const; void setValuesTyped(Type*, const std::vector&); bool filter(const MarsRequest& filter); bool matches(const MarsRequest& filter) const; bool empty() const; size_t count() const; MarsRequest extract(const std::string& category) const; void erase(const std::string& param); std::string asString() const; public: // static methods static MarsRequest parse(const std::string& s, bool strict = false); static std::vector parse(std::istream&, bool strict = false); /// Implementation in api/metkit_c.cc static const MarsRequest& fromOpaque(const metkit_marsrequest_t* request); private: // members std::string verb_; std::list params_; private: // methods void print(std::ostream&) const; void encode(eckit::Stream&) const; std::list::const_iterator find(const std::string&) const; std::list::iterator find(const std::string&); // -- Class members static eckit::ClassSpec classSpec_; static eckit::Reanimator reanimator_; friend std::ostream& operator<<(std::ostream& s, const MarsRequest& r) { r.print(s); return s; } friend eckit::JSON& operator<<(eckit::JSON& s, const MarsRequest& r) { r.json(s); return s; } friend eckit::Stream& operator<<(eckit::Stream& s, const MarsRequest& r) { r.encode(s); return s; } }; template size_t MarsRequest::getValues(const std::string& name, std::vector& v, bool emptyOk) const { const std::vector& s = values(name, emptyOk); eckit::Translator t; v.clear(); for (std::vector::const_iterator j = s.begin(); j != s.end(); ++j) { v.push_back(t(*j)); } return v.size(); } template void MarsRequest::setValue(const std::string& name, const T& value) { eckit::Translator t; std::vector v(1, t(value)); values(name, v); } //---------------------------------------------------------------------------------------------------------------------- } // namespace metkit::mars #endif metkit-1.16.0/src/metkit/mars/MarsRequestHandle.cc000066400000000000000000000100031513171467200220210ustar00rootroot00000000000000/* * (C) Copyright 1996- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ // File MarsRequestHandle.cc // Baudouin Raoult - (c) ECMWF Feb 12 #include "metkit/mars/MarsRequestHandle.h" #include "metkit/config/LibMetkit.h" #include "eckit/types/Types.h" #include "eckit/utils/StringTools.h" namespace metkit { namespace mars { static eckit::Reanimator marsRequestHandleReanimator; const eckit::ReanimatorBase& MarsRequestHandle::reanimator() const { return marsRequestHandleReanimator; } const eckit::ClassSpec& MarsRequestHandle::classSpec() { static eckit::ClassSpec spec = {&eckit::DataHandle::classSpec(), "MarsRequestHandle"}; return spec; } bool shortName(const std::string& prefix, const std::string& s) { if (prefix.size() > s.size()) return false; return std::equal(prefix.begin(), prefix.end(), s.begin()); } MarsRequestHandle::MarsRequestHandle(eckit::Stream& s) : eckit::DataHandle(s), request_(s), protocol_(eckit::Reanimator::reanimate(s)), opened_(false) {} MarsRequestHandle::MarsRequestHandle(const MarsRequest& request, BaseProtocol* protocol) : request_(request), protocol_(protocol), opened_(false) { LOG_DEBUG_LIB(LibMetkit) << "MarsRequestHandle::MarsRequestHandle: request: " << request << " protocol: " << protocol << std::endl; ASSERT(protocol); } MarsRequestHandle::MarsRequestHandle(const metkit::mars::MarsRequest& request, const eckit::Configuration& database) : request_(request.verb()), protocol_(ProtocolFactory::build(database)), opened_(false) { for (const auto& p : request.parameters()) { request_.values(p.name(), p.values()); } } MarsRequestHandle::~MarsRequestHandle() { if (opened_) { close(); } } eckit::Length MarsRequestHandle::openForRead() { eckit::Log::info() << "MarsRequestHandle::openForRead[" << request_ << "]" << std::endl; ASSERT(!opened_); opened_ = true; const std::string v(eckit::StringTools::lower(request_.verb())); ASSERT(v == "retrieve" || v == "stage" || v == "list" || v == "get"); return protocol_->retrieve(request_); } void MarsRequestHandle::openForWrite(const eckit::Length& size) { eckit::Log::info() << "MarsRequestHandle::openForWrite[" << request_ << "]" << std::endl; ASSERT(!opened_); opened_ = true; ASSERT(eckit::StringTools::lower(request_.verb()) == "archive"); protocol_->archive(request_, size); } void MarsRequestHandle::openForAppend(const eckit::Length&) { eckit::Log::info() << "MarsRequestHandle::openForAppend[" << request_ << "]" << std::endl; ASSERT(!opened_); opened_ = true; NOTIMP; } long MarsRequestHandle::read(void* buffer, long len) { ASSERT(opened_); try { return protocol_->read(buffer, len); } catch (eckit::Exception& e) { std::ostringstream oss; oss << "Exception " << e.what() << " caught in MarsRequestHandle::read(" << *protocol_ << ")"; eckit::Log::error() << oss.str() << std::endl; throw RetryTransfer(oss.str()); } } long MarsRequestHandle::write(const void* buffer, long len) { ASSERT(opened_); return protocol_->write(buffer, len); } void MarsRequestHandle::close() { eckit::Log::info() << "MarsRequestHandle::close[" << request_ << "]" << std::endl; opened_ = false; protocol_->cleanup(); } void MarsRequestHandle::print(std::ostream& s) const { s << "MarsRequestHandle[" << *protocol_ << "," << request_ << "]"; } void MarsRequestHandle::encode(eckit::Stream& s) const { eckit::DataHandle::encode(s); s << request_; s << *protocol_; } bool MarsRequestHandle::canSeek() const { return false; } } // namespace mars } // namespace metkit metkit-1.16.0/src/metkit/mars/MarsRequestHandle.h000066400000000000000000000041121513171467200216670ustar00rootroot00000000000000/* * (C) Copyright 1996- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ // File MarsRequestHandle.h // Baudouin Raoult - (c) ECMWF Feb 12 #ifndef MarsRequestHandle_H #define MarsRequestHandle_H #include #include "eckit/exception/Exceptions.h" #include "eckit/io/DataHandle.h" #include "metkit/mars/BaseProtocol.h" #include "metkit/mars/MarsRequest.h" namespace metkit { namespace mars { class MarsRequestHandle : public eckit::DataHandle { public: class RetryTransfer : public eckit::Exception { virtual bool retryOnClient() const { return true; } public: RetryTransfer(const std::string& what) : eckit::Exception(what) {} }; public: MarsRequestHandle(eckit::Stream&); MarsRequestHandle(const metkit::mars::MarsRequest& request, const eckit::Configuration& database); MarsRequestHandle(const metkit::mars::MarsRequest& request, metkit::mars::BaseProtocol* protocol); ~MarsRequestHandle(); // -- Overridden methods (from Streamable) virtual std::string className() const override { return "MarsRequestHandle"; } virtual const eckit::ReanimatorBase& reanimator() const override; static const eckit::ClassSpec& classSpec(); private: // members metkit::mars::MarsRequest request_; std::unique_ptr protocol_; bool opened_; private: // members void print(std::ostream&) const override; void encode(eckit::Stream&) const override; eckit::Length openForRead() override; void openForWrite(const eckit::Length&) override; void openForAppend(const eckit::Length&) override; long read(void*, long) override; long write(const void*, long) override; void close() override; bool canSeek() const override; }; } // namespace mars } // namespace metkit #endif metkit-1.16.0/src/metkit/mars/Matcher.cc000066400000000000000000000103311513171467200200210ustar00rootroot00000000000000/* * (C) Copyright 2025- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ /// @author Chris Bradley #include #include #include #include #include "eckit/exception/Exceptions.h" #include "eckit/utils/Overloaded.h" #include "eckit/utils/Regex.h" #include "eckit/utils/Tokenizer.h" #include "metkit/mars/MarsRequest.h" #include "metkit/mars/Matcher.h" namespace metkit::mars { // ---------------------------------------------------------------------------------------------------------------------- namespace { // helpers class MarsRequestAccessor : public RequestLike { public: explicit MarsRequestAccessor(const metkit::mars::MarsRequest& request) : request_(request) {} std::optional get(const std::string& keyword) const override { return request_.get(keyword); } private: const metkit::mars::MarsRequest& request_; }; inline std::string trim(const std::string& s) { auto start = std::find_if_not(s.begin(), s.end(), [](unsigned char ch) { return std::isspace(ch); }); auto end = std::find_if_not(s.rbegin(), s.rend(), [](unsigned char ch) { return std::isspace(ch); }).base(); if (start >= end) { return ""; // string is all whitespace } return std::string(start, end); } } // namespace // ---------------------------------------------------------------------------------------------------------------------- std::map parseMatchString(const std::string& expr) { if (expr.empty()) { throw eckit::BadValue("Empty match expression", Here()); } std::vector key_vals; eckit::Tokenizer(',')(expr, key_vals); eckit::Tokenizer equals('='); std::map out; for (const std::string& item : key_vals) { std::vector kv; equals(item, kv); if (kv.size() != 2) { throw eckit::BadValue("Invalid condition " + item + " in expression: " + expr, Here()); } const std::string& key = trim(kv[0]); const std::string& val = trim(kv[1]); auto [it, inserted] = out.try_emplace(key, val); if (!inserted) { throw eckit::BadValue("Duplicate key " + key + " in expression: " + expr, Here()); } } return out; } // ---------------------------------------------------------------------------------------------------------------------- Matcher::Matcher(std::map regexMap, Policy policy) : regexMap_{std::move(regexMap)}, policy_{policy} {} Matcher::Matcher(const std::string& expr, Policy policy) : regexMap_{parseMatchString(expr)}, policy_{policy} {} bool Matcher::match(const MarsRequest& request, MatchMissingPolicy matchOnMissing) const { return match(MarsRequestAccessor(request), matchOnMissing); } bool Matcher::match(const RequestLike& request, MatchMissingPolicy matchOnMissing) const { return std::all_of(regexMap_.begin(), regexMap_.end(), [&](const auto& kv) { const auto& keyword = kv.first; const auto& regex = kv.second; auto opt_values = request.get(keyword); if (!opt_values) return matchOnMissing == MatchOnMissing; auto pred = [®ex](const std::string& s) { return regex.match(s); }; // clang-format off return std::visit(eckit::Overloaded { [&](std::reference_wrapper value) { return pred(value.get()); }, [&](std::reference_wrapper> values) { const auto& vec = values.get(); if (policy_ == Policy::Any) { return std::any_of(vec.begin(), vec.end(), pred); } ASSERT(policy_ == Policy::All); return std::all_of(vec.begin(), vec.end(), pred); } }, *opt_values); // clang-format on }); } } // namespace metkit::marsmetkit-1.16.0/src/metkit/mars/Matcher.h000066400000000000000000000056741513171467200177010ustar00rootroot00000000000000/* * (C) Copyright 2025- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ /// @author Chris Bradley /// @date Sep 2025 #pragma once #include #include #include #include #include "eckit/utils/Regex.h" #include "metkit/mars/MarsRequest.h" namespace metkit::mars { class RequestLike; /// Parse a match expression into a map of key:regex pairs /// @param expr is a series of comma separated key:regex pairs e.g. /// "expver=(0001|o[0-9a-z]{3}),dataset=^climate-dt$" std::map parseMatchString(const std::string& expr); // ------------------------------------------------------------------------------------------------------------- /// For matching requests against a set of key:regex conditions. For constructing select/exclude filters. class Matcher { public: /// Policy for handling requests with multiple values for a given key. enum class Policy { All, ///< Require all values to match Any ///< Require at least one value to match }; /// Policy for handling keys in the matcher that are absent in the request. enum class MatchMissingPolicy { MatchOnMissing, DontMatchOnMissing }; static constexpr auto MatchOnMissing = MatchMissingPolicy::MatchOnMissing; static constexpr auto DontMatchOnMissing = MatchMissingPolicy::DontMatchOnMissing; public: /// Construct a matcher from a map of key:regex pairs Matcher(std::map regexMap, Policy policy); Matcher(const std::string& expr, Policy policy); bool match(const RequestLike& request, MatchMissingPolicy matchOnMissing = MatchOnMissing) const; bool match(const MarsRequest& request, MatchMissingPolicy matchOnMissing = MatchOnMissing) const; private: std::map regexMap_; Policy policy_; }; // ---------------------------------------------------------------------------------------------------------------------- /// Interface to access keyword / value(s) pairs across similar types. /// Designed to allow uniform access to keywords / values for MarsRequest / fdb5::Key class RequestLike { public: using values_t = std::variant, ///< single value std::reference_wrapper> ///< multiple values >; virtual ~RequestLike() = default; /// Get a reference_wrapper to the value(s) for the given keyword, or nullopt if not found virtual std::optional get(const std::string& keyword) const = 0; }; } // namespace metkit::marsmetkit-1.16.0/src/metkit/mars/Param.cc000066400000000000000000000034651513171467200175100ustar00rootroot00000000000000/* * (C) Copyright 1996- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ #include "metkit/mars/Param.h" #include "eckit/exception/Exceptions.h" #include "eckit/persist/DumpLoad.h" #include "eckit/utils/Tokenizer.h" using namespace eckit; namespace metkit { //---------------------------------------------------------------------------------------------------------------------- Param::Param(const std::string& s) { Tokenizer parse("."); std::vector result; parse(s, result); switch (result.size()) { case 1: value_ = atol(result[0].c_str()); table_ = 0; break; case 2: value_ = atol(result[0].c_str()); table_ = atol(result[1].c_str()); break; default: throw eckit::BadValue("Invalid param"); } } Param::operator std::string() const { std::ostringstream os; os << *this; return os.str(); } void Param::print(std::ostream& s) const { if (table_) s << value_ << '.' << table_; else s << value_; } void Param::dump(DumpLoad& a) const { a.dump(value_); a.dump(table_); } void Param::load(DumpLoad& a) { a.load(value_); a.load(table_); } long Param::paramId() const { size_t t = table_ == 0 ? value_ / 1000 : table_; return (t == 128 ? 0 : t * 1000) + value_ % 1000; } //---------------------------------------------------------------------------------------------------------------------- } // namespace metkit metkit-1.16.0/src/metkit/mars/Param.h000066400000000000000000000040521513171467200173430ustar00rootroot00000000000000/* * (C) Copyright 1996- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ // File Param.h // Baudouin Raoult - ECMWF Dec 97 #ifndef metkit_Param_H #define metkit_Param_H #include #include "eckit/persist/Bless.h" namespace eckit { class DumpLoad; } namespace metkit { //---------------------------------------------------------------------------------------------------------------------- class Param { public: Param() : table_(-1), value_(-1) {} Param(const std::string&); Param(long table, long value) : table_(table), value_(value) {} #include "metkit/mars/Param.b" ~Param() {} operator std::string() const; bool operator==(const Param& other) const { return value_ == other.value_ && table_ == other.table_; } bool operator!=(const Param& other) const { return value_ != other.value_ || table_ != other.table_; } bool operator<(const Param& other) const { return (value_ == other.value_) ? (table_ < other.table_) : (value_ < other.value_); } bool operator>(const Param& other) const { return (value_ == other.value_) ? (table_ > other.table_) : (value_ > other.value_); } long table() const { return table_; } long value() const { return value_; } long grib1value() const { return value_ % 1000; } long paramId() const; void dump(eckit::DumpLoad&) const; void load(eckit::DumpLoad&); protected: void print(std::ostream& s) const; private: long table_; long value_; friend std::ostream& operator<<(std::ostream& s, const Param& p) { p.print(s); return s; } }; //---------------------------------------------------------------------------------------------------------------------- } // namespace metkit #endif metkit-1.16.0/src/metkit/mars/ParamID.cc000066400000000000000000000061041513171467200177160ustar00rootroot00000000000000/* * (C) Copyright 1996- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ #include "metkit/mars/ParamID.h" #include #include #include "eckit/config/Resource.h" #include "eckit/parser/YAMLParser.h" #include "eckit/system/Library.h" #include "eckit/utils/Tokenizer.h" #include "metkit/config/LibMetkit.h" using namespace eckit; namespace metkit { //---------------------------------------------------------------------------------------------------------------------- static std::vector windFamilies_; static std::vector dropTables_; static bool fullTableDropping_; static std::set mlParamsSingleLevel_; //---------------------------------------------------------------------------------------------------------------------- static pthread_once_t once = PTHREAD_ONCE_INIT; static void readTable() { eckit::PathName paramMatchingPath = eckit::Resource("paramMatchingPath;$PARAM_MATCHING_PATH", LibMetkit::paramMatchingYamlFile()); const eckit::Value paramMatching = eckit::YAMLParser::decodeFile(paramMatchingPath); const eckit::Value wind = paramMatching["wind"]; ASSERT(wind.isList()); for (size_t i = 0; i < wind.size(); ++i) { const eckit::Value s = wind[i]; ASSERT(s.isList()); ASSERT(s.size() == 4); windFamilies_.push_back(ParamID::WindFamily(s[0], s[1], s[2], s[3])); } const eckit::Value dropTables = paramMatching["drop-tables"]; ASSERT(dropTables.isList()); for (size_t i = 0; i < dropTables.size(); ++i) { dropTables_.push_back(dropTables[i]); } fullTableDropping_ = false; if (paramMatching.contains("full-table-dropping")) { const eckit::Value fullTableDropping = paramMatching["full-table-dropping"]; ASSERT(fullTableDropping.isBool()); fullTableDropping_ = fullTableDropping; } const eckit::Value mlParamsSingleLevel = paramMatching["ml-params-single-level"]; ASSERT(mlParamsSingleLevel.isList()); for (size_t i = 0; i < mlParamsSingleLevel.size(); ++i) { mlParamsSingleLevel_.insert(mlParamsSingleLevel[i]); } } const std::vector& ParamID::getWindFamilies() { pthread_once(&once, readTable); return windFamilies_; } const std::vector& ParamID::getDropTables() { pthread_once(&once, readTable); return dropTables_; } const std::set& ParamID::getMlParamsSingleLevel() { pthread_once(&once, readTable); return mlParamsSingleLevel_; } bool ParamID::fullTableDropping() { pthread_once(&once, readTable); return fullTableDropping_; } //---------------------------------------------------------------------------------------------------------------------- } // namespace metkit metkit-1.16.0/src/metkit/mars/ParamID.h000066400000000000000000000265461513171467200175740ustar00rootroot00000000000000/* * (C) Copyright 1996- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ /// @author Baudouin Raoult /// @author Tiago Quintino /// @author Simon Smart /// @date Febuary 2019 #ifndef metkit_ParamID_H #define metkit_ParamID_H #include #include #include #include #include "eckit/config/Resource.h" #include "eckit/filesystem/PathName.h" #include "eckit/log/Log.h" #include "eckit/runtime/Metrics.h" #include "eckit/types/Types.h" #include "metkit/config/LibMetkit.h" #include "metkit/mars/Param.h" namespace metkit { //---------------------------------------------------------------------------------------------------------------------- class ParamID { public: // types struct WindFamily { Param u_; Param v_; Param vo_; Param d_; WindFamily(const std::string& u, const std::string& v, const std::string& vo, const std::string& d) : u_(u), v_(v), vo_(vo), d_(d) {} }; public: // methods template static void normalise(const REQUEST_T& r, std::vector& req, const AXIS_T& axis, bool& windConversion, bool fullTableDropping = ParamID::fullTableDropping()); static const std::vector& getWindFamilies(); static const std::vector& getDropTables(); static bool fullTableDropping(); static const std::set& getMlParamsSingleLevel(); }; //---------------------------------------------------------------------------------------------------------------------- inline long replaceTable(size_t table, long paramid) { return (table * 1000 + paramid % 1000); } template void ParamID::normalise(const REQUEST_T& request, std::vector& req, const AXIS_T& axis, bool& windConversion, bool fullTableDropping) { static const bool useGRIBParamID = eckit::Resource("useGRIBParamID", false); const std::vector& windFamilies(getWindFamilies()); if (useGRIBParamID) { std::set inAxis; for (typename AXIS_T::const_iterator j = axis.begin(); j != axis.end(); ++j) { inAxis.insert((*j)); } std::vector newreq; newreq.reserve(req.size()); for (std::vector::const_iterator k = req.begin(); k != req.end(); ++k) { const Param& p = (*k); Param alt; if (p.table()) { alt = Param(0, (p.table() == 128 ? 0 : p.table()) * 1000 + p.value()); // No '.' version } else { size_t t = p.value() / 1000; size_t v = p.value() % 1000; alt = Param(t == 0 ? 128 : t, v); // '.' version } if (inAxis.find(p) != inAxis.end()) { newreq.push_back(p); } else if (inAxis.find(alt) != inAxis.end()) { newreq.push_back(alt); } else { newreq.push_back(p); } LOG_DEBUG_LIB(LibMetkit) << "useGRIBParamID p=" << p << ", alt=" << alt << ", choice=" << newreq.back() << std::endl; } req = newreq; for (eckit::Ordinal w = 0; w < windFamilies.size(); w++) { const Param windU(windFamilies[w].u_); const Param windV(windFamilies[w].v_); const Param windVO(windFamilies[w].vo_); const Param windD(windFamilies[w].d_); bool wantU = false; bool wantV = false; bool wantVO = false; bool wantD = false; // Check if wind is requested for (eckit::Ordinal i = 0; i < req.size(); i++) { if (req[i] == windU) wantU = true; if (req[i] == windV) wantV = true; if (req[i] == windVO) wantVO = true; if (req[i] == windD) wantD = true; } // Check if we have got it, axis should be sorted bool gotU = false; bool gotV = false; if (wantU) gotU = std::binary_search(axis.begin(), axis.end(), windU); if (wantV) gotV = std::binary_search(axis.begin(), axis.end(), windV); if ((wantU && !gotU) || (wantV && !gotV)) { // Push VO and D if needed if (!wantVO) req.push_back(windVO); if (!wantD) req.push_back(windD); LOG_DEBUG_LIB(LibMetkit) << "U/V conversion requested U=" << windU << ", V=" << windV << ", VO=" << windVO << ", D=" << windD << std::endl; windConversion = true; } } } else { std::vector > tableDropped; std::set inAxis; std::map inAxisParamID; std::set wind; for (typename AXIS_T::const_iterator j = axis.begin(); j != axis.end(); ++j) { inAxis.emplace(*j); inAxisParamID[j->paramId()] = *j; } std::vector newreq; newreq.reserve(req.size()); for (auto r : req) { if (inAxis.find(r) != inAxis.end()) { // Perfect match - look no further newreq.push_back(r); } else { // r is normalised to ParamID long paramid = r.paramId(); auto ap = inAxisParamID.find(paramid); if (ap != inAxisParamID.end()) { // ParamID representation matching - look no further newreq.push_back(ap->second); } else { // Special case for U/V - exact match bool ok = false; for (eckit::Ordinal w = 0; w < windFamilies.size(); w++) { if ((paramid == windFamilies[w].u_.paramId() || paramid == windFamilies[w].u_.grib1value() || paramid == windFamilies[w].v_.paramId() || paramid == windFamilies[w].v_.grib1value()) && inAxis.find(windFamilies[w].vo_) != inAxis.end() && inAxis.find(windFamilies[w].d_) != inAxis.end()) { if (paramid == windFamilies[w].u_.paramId() || paramid == windFamilies[w].u_.grib1value()) newreq.push_back(windFamilies[w].u_); else newreq.push_back(windFamilies[w].v_); wind.emplace(windFamilies[w].vo_); wind.emplace(windFamilies[w].d_); windConversion = true; ok = true; break; } } if (!ok && r.table() == 0 && paramid < 1000) { // Partial match (only it table has not been specified by user) const std::vector& dropTables = ParamID::getDropTables(); for (auto t : dropTables) { auto ap = inAxisParamID.find(replaceTable(t, paramid)); if (ap != inAxisParamID.end()) { // ParamID representation matching - look no further newreq.push_back(ap->second); ok = true; break; } } if (!ok) { // Special case for U/V - partial match for (eckit::Ordinal w = 0; !ok && w < windFamilies.size(); w++) { if (paramid == windFamilies[w].u_.paramId() || paramid == windFamilies[w].v_.paramId()) { for (auto t : dropTables) { auto vo = inAxisParamID.find(replaceTable(t, windFamilies[w].vo_.paramId())); auto d = inAxisParamID.find(replaceTable(t, windFamilies[w].d_.paramId())); if (vo != inAxisParamID.end() && d != inAxisParamID.end()) { bool grib1 = vo->second.table() > 0; if (paramid == windFamilies[w].u_.paramId()) newreq.push_back(grib1 ? Param(t, paramid) : Param(0, replaceTable(t, paramid))); else newreq.push_back(grib1 ? Param(t, paramid) : Param(0, replaceTable(t, paramid))); wind.emplace(vo->second); wind.emplace(d->second); windConversion = true; ok = true; break; } } if (ok) break; } } } if (fullTableDropping && !ok) { // Backward compatibility - Partial match (drop completely table information) for (auto ap : inAxisParamID) { if (ap.first % 1000 == paramid % 1000) { newreq.push_back(ap.second); ok = true; tableDropped.push_back(std::make_pair(r, ap.second)); break; } } } } } } } req = newreq; for (auto w : wind) { bool exist = false; for (eckit::Ordinal i = 0; i < req.size(); i++) if (req[i] == w) { exist = true; break; } if (!exist) { req.push_back(w); } } if (tableDropped.size() > 0) { eckit::MetricsPrefix prefix("paramid_normalisation"); { std::ostringstream oss; oss << request; eckit::Metrics::set("user_request", oss.str()); } { std::ostringstream oss; oss << tableDropped; eckit::Metrics::set("params", oss.str()); } } } } //---------------------------------------------------------------------------------------------------------------------- } // namespace metkit #endif metkit-1.16.0/src/metkit/mars/Parameter.cc000066400000000000000000000064131513171467200203640ustar00rootroot00000000000000/* * (C) Copyright 1996- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ #include #include #include "metkit/mars/Parameter.h" #include "metkit/mars/Type.h" namespace metkit { namespace mars { //---------------------------------------------------------------------------------------------------------------------- class UndefinedType : public Type { void print(std::ostream& out) const override { out << ""; } bool expand(std::string&, const MarsRequest&) const override { NOTIMP; } public: UndefinedType() : Type("", eckit::Value()) { attach(); } }; static UndefinedType undefined; //---------------------------------------------------------------------------------------------------------------------- Parameter::Parameter() : type_(&undefined) { type_->attach(); } Parameter::~Parameter() { type_->detach(); } Parameter::Parameter(const std::vector& values, Type* type) : type_(type), values_(values) { if (!type) { type_ = &undefined; } type_->attach(); } Parameter::Parameter(const Parameter& other) : type_(other.type_), values_(other.values_) { type_->attach(); } Parameter& Parameter::operator=(const Parameter& other) { Type* old = type_; type_ = other.type_; type_->attach(); old->detach(); values_ = other.values_; return *this; } void Parameter::values(const std::vector& values) { values_ = values; } bool Parameter::filter(const std::vector& filter) { return type_->filter(filter, values_); } bool Parameter::filter(const std::string& keyword, const std::vector& filter) { return type_->filter(keyword, filter, values_); } bool Parameter::matches(const std::vector& match) const { return type_->matches(match, values_); } void Parameter::merge(const Parameter& p) { ASSERT(name() == p.name()); /// @note this isn't optimal O(N^2) but it respects the order std::vector diff; for (auto& o : p.values_) { bool found = false; for (auto& v : values_) { if (v == o) { found = true; break; } } if (!found) diff.push_back(o); } values_.insert(values_.end(), std::make_move_iterator(diff.begin()), std::make_move_iterator(diff.end())); } const std::string& Parameter::name() const { return type_->name(); } size_t Parameter::count() const { return type_->count(values_); } void Parameter::print(std::ostream& s) const { s << "Parameter[type=" << *type_ << ",values=" << values_ << "]"; } bool Parameter::operator<(const Parameter& other) const { if (name() != other.name()) { return name() < other.name(); } return values_ < other.values_; } //---------------------------------------------------------------------------------------------------------------------- } // namespace mars } // namespace metkit metkit-1.16.0/src/metkit/mars/Parameter.h000066400000000000000000000041421513171467200202230ustar00rootroot00000000000000/* * (C) Copyright 1996- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ /// @author Manuel Fuentes /// @author Baudouin Raoult /// @author Tiago Quintino /// @date Sep 96 #ifndef metkit_Parameter_H #define metkit_Parameter_H #include "eckit/types/Date.h" #include "eckit/types/Double.h" #include "eckit/types/Time.h" #include "eckit/utils/Translator.h" #include "eckit/value/Value.h" namespace eckit { class JSON; class MD5; } // namespace eckit namespace metkit { namespace mars { class Type; class MarsRequest; //---------------------------------------------------------------------------------------------------------------------- class Parameter { public: // methods Parameter(); ~Parameter(); Parameter(const std::vector& values, Type* = 0); Parameter(const Parameter&); Parameter& operator=(const Parameter&); bool operator<(const Parameter&) const; const std::vector& values() const { return values_; } void values(const std::vector& values); bool filter(const std::vector& filter); bool filter(const std::string& keyword, const std::vector& filter); bool matches(const std::vector& matches) const; void merge(const Parameter& p); Type& type() const { return *type_; } const std::string& name() const; size_t count() const; private: // methods void print(std::ostream&) const; friend std::ostream& operator<<(std::ostream& s, const Parameter& p) { p.print(s); return s; } private: // members Type* type_; std::vector values_; }; //---------------------------------------------------------------------------------------------------------------------- } // namespace mars } // namespace metkit #endif metkit-1.16.0/src/metkit/mars/Quantile.cc000066400000000000000000000060711513171467200202260ustar00rootroot00000000000000/* * (C) Copyright 1996- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ #include #include "eckit/exception/Exceptions.h" #include "eckit/utils/Tokenizer.h" #include "metkit/mars/Quantile.h" using namespace eckit; namespace metkit { //---------------------------------------------------------------------------------------------------------------------- Quantile::Quantile(const std::string& value) { Tokenizer parse(":"); std::vector result; parse(value, result); if (result.size() != 2) { std::ostringstream oss; oss << "Quantile " << value << " must be in the form :"; throw eckit::BadValue(oss.str()); } try { num_ = std::stol(result[0]); den_ = std::stol(result[1]); } catch (const std::invalid_argument& e) { std::ostringstream oss; oss << "Quantile " << value << " must be in the form :"; throw eckit::BadValue(oss.str()); } check(); } void Quantile::check() const { if (num_ < 0) { std::ostringstream oss; oss << "Quantile numerator " << num_ << " must be non negative"; throw eckit::BadValue(oss.str()); } if (den_ < 0) { std::ostringstream oss; oss << "Quantile denominator " << den_ << " must be non negative"; throw eckit::BadValue(oss.str()); } if (den_ < num_) { std::ostringstream oss; oss << "Quantile numerator " << num_ << " must be less or equal the value of denominator " << den_; throw eckit::BadValue(oss.str()); } } Quantile::Quantile(long num, long den) : num_(num), den_(den) { check(); } Quantile::operator std::string() { std::ostringstream oss; oss << num_ << ':' << den_; return oss.str(); } void Quantile::print(std::ostream& s) const { s << num_ << ':' << den_; } Quantile& Quantile::operator+=(const long& rhs) { num_ += rhs; check(); return *this; } Quantile& Quantile::operator-=(const long& rhs) { num_ -= rhs; check(); return *this; } bool operator==(const Quantile& lhs, const Quantile& rhs) { if (lhs.den() != rhs.den()) { std::ostringstream oss; oss << "Quantile values must belong to the same quantile group"; throw eckit::BadValue(oss.str()); } return (lhs.num() == rhs.num()); } bool operator<(const Quantile& lhs, const Quantile& rhs) { if (lhs.den() != rhs.den()) { std::ostringstream oss; oss << "Quantile values must belong to the same quantile group"; throw eckit::BadValue(oss.str()); } return (lhs.num() < rhs.num()); } //---------------------------------------------------------------------------------------------------------------------- } // namespace metkit metkit-1.16.0/src/metkit/mars/Quantile.h000066400000000000000000000034441513171467200200710ustar00rootroot00000000000000/* * (C) Copyright 1996- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ /// @file Quantile.h /// @author Emanuele Danovaro /// @date February 2022 #pragma once #include namespace metkit { //---------------------------------------------------------------------------------------------------------------------- class Quantile { public: Quantile(const std::string& value); Quantile(long num, long den); long num() const { return num_; } long den() const { return den_; } operator std::string(); Quantile& operator+=(const long& rhs); Quantile& operator-=(const long& rhs); protected: void print(std::ostream& s) const; private: void check() const; friend std::ostream& operator<<(std::ostream& s, const Quantile& q) { q.print(s); return s; } private: long num_; long den_; }; bool operator==(const Quantile& lhs, const Quantile& rhs); inline bool operator!=(const Quantile& lhs, const Quantile& rhs) { return !(rhs == lhs); } bool operator<(const Quantile& lhs, const Quantile& rhs); inline bool operator>(const Quantile& lhs, const Quantile& rhs) { return rhs < lhs; } inline bool operator<=(const Quantile& lhs, const Quantile& rhs) { return !(lhs > rhs); } inline bool operator>=(const Quantile& lhs, const Quantile& rhs) { return !(lhs < rhs); } //---------------------------------------------------------------------------------------------------------------------- } // namespace metkit metkit-1.16.0/src/metkit/mars/RequestEnvironment.cc000066400000000000000000000037761513171467200223320ustar00rootroot00000000000000/* * (C) Copyright 1996- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ #include "metkit/mars/RequestEnvironment.h" #include #include #include #include #include #include "eckit/runtime/Main.h" #include "eckit/system/SystemInfo.h" #include "eckit/utils/Tokenizer.h" namespace metkit::mars { RequestEnvironment::RequestEnvironment(const RequestEnvironment& other) : env_(other.env_) {} void RequestEnvironment::update(const std::map& env) { // Split string on '/' and ignore empty splits const auto split = [](const std::string& str) -> std::vector { std::vector result; eckit::Tokenizer parse("/"); parse(str, result); return result; }; for (const auto& [k, v] : env) { env_->values(k, split(v)); } } void RequestEnvironment::initialize(const std::map& env) { RequestEnvironment& re = inst(); std::lock_guard lock(re.init_); re.env_.emplace("environ"); re.env_->setValue("host", eckit::Main::hostname()); re.env_->setValue("user", eckit::system::SystemInfo::instance().userName()); re.env_->setValue("pid", getpid()); re.env_->setValue("client", "unknown"); re.update(env); } RequestEnvironment& RequestEnvironment::inst() { static RequestEnvironment e; return e; } const RequestEnvironment& RequestEnvironment::instance() { auto& re = RequestEnvironment::inst(); std::lock_guard lock(re.init_); if (!re.env_) { throw eckit::SeriousBug("RequestEnvironment not initialized"); } return re; } } // namespace metkit::mars metkit-1.16.0/src/metkit/mars/RequestEnvironment.h000066400000000000000000000035131513171467200221610ustar00rootroot00000000000000/* * (C) Copyright 1996- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation * nor does it submit to any jurisdiction. */ /// @author Baudouin Raoult /// @author Tiago Quintino #pragma once #include #include #include #include #include "metkit/mars/MarsRequest.h" namespace metkit::mars { /// Encapsulates the environment to be sent to the mars-server. /// This uses a mars request with 'environ' as the verb and each environment /// variable is treated as keyword with its respective value. class RequestEnvironment { public: RequestEnvironment(const RequestEnvironment& other); /// Create the actual "mars-request" /// @return the request const MarsRequest& request() const { return *env_; } /// @brief Initialize the RequestEnvironment with a map of KEYWORD:VALUE(s). /// @param env, map of KEYWORD:VALUE (or KEYWORD:VALUE1/VALUE2/.../VALUEn) to add to the environment. static void initialize(const std::map& env); /// @brief Update the RequestEnvironment with a map of KEYWORD:VALUE(s). /// @param env, map of KEYWORD:VALUE (or KEYWORD:VALUE1/VALUE2/.../VALUEn) to add to the environment. void update(const std::map& env); /// Access instance of RequestEnvironment /// @return RequestEnvironment static const RequestEnvironment& instance(); private: RequestEnvironment() = default; static RequestEnvironment& inst(); std::optional env_ = std::nullopt; std::recursive_mutex init_; }; } // namespace metkit::mars metkit-1.16.0/src/metkit/mars/StepRange.cc000066400000000000000000000105061513171467200203320ustar00rootroot00000000000000/* * (C) Copyright 1996- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ #include "metkit/mars/StepRange.h" #include "metkit/mars/TypeRange.h" #include "metkit/mars/TypeTime.h" #include "eckit/exception/Exceptions.h" #include "eckit/persist/DumpLoad.h" #include "eckit/utils/Tokenizer.h" using namespace eckit; //---------------------------------------------------------------------------------------------------------------------- namespace { // enum TimeUnit { // Second = 0, // Minute = 1, // Hour = 2, // Day = 3 // }; // TimeUnit maxUnit(const eckit::Time& t) { // if (t.seconds() == 0) { // if (t.minutes() == 0) { // if (t.hours() == 0) { // return TimeUnit::Day; // } // return TimeUnit::Hour; // } // return TimeUnit::Minute; // } // return TimeUnit::Second; // } std::string canonical(const eckit::Time& time, bool useDays, bool alwaysUseHours) { long h = time.hours(); long m = time.minutes(); long s = time.seconds(); long d = 0; if (useDays && h > 23) { d = h / 24; h = h % 24; } std::string out = ""; if (d != 0) { out += std::to_string(d) + "d"; } if (h != 0 || (m == 0 && s == 0 && d == 0)) { out += std::to_string(h); if (alwaysUseHours || m != 0 || s != 0 || d != 0) { out += "h"; } } if (m != 0) { out += std::to_string(m) + "m"; } if (s != 0) { out += std::to_string(s) + "s"; } return out; } // std::string canonical(const eckit::Time& time, TimeUnit unit) { // switch (unit) { // case TimeUnit::Second: // return std::to_string(time.seconds()+60*time.minutes()+3600*time.hours()) + "s"; // case TimeUnit::Minute: // return std::to_string(time.minutes()+60*time.hours()) + "m"; // case TimeUnit::Day: // case TimeUnit::Hour: // default: // return std::to_string(time.hours()); // } // } } // namespace namespace metkit::mars { //---------------------------------------------------------------------------------------------------------------------- StepRange::operator std::string() const { return toString(); } std::string StepRange::toString(bool useDays, bool alwaysUseHours) const { std::ostringstream os; print(os, useDays, alwaysUseHours); return os.str(); } void StepRange::print(std::ostream& s, bool useDays, bool alwaysUseHours) const { if (from_ == to_) { s << canonical(eckit::Time(std::lround(from_ * 3600.), true), useDays, alwaysUseHours); } else { eckit::Time f{std::lround(from_ * 3600.), true}; eckit::Time t{std::lround(to_ * 3600.), true}; s << canonical(f, useDays, alwaysUseHours) << '-' << canonical(t, useDays, alwaysUseHours); } } StepRange::StepRange(const std::string& s) : from_(0.), to_(0.) { Tokenizer parse("-"); std::vector result; // negative steps are not supported if (s[0] != '-') parse(s, result); switch (result.size()) { case 1: to_ = from_ = eckit::Time(result[0], true) / 3600.; break; case 2: from_ = eckit::Time(result[0], true) / 3600.; to_ = eckit::Time(result[1], true) / 3600.; if (from_ > to_) { std::ostringstream oss; oss << "initial value " << from_ << " cannot be greater that final value " << to_; throw eckit::BadValue(oss.str(), Here()); } break; default: std::ostringstream msg; msg << "Bad StepRange [" << s << "]"; throw eckit::BadValue(msg.str(), Here()); } } void StepRange::dump(DumpLoad& a) const { a.dump(from_); a.dump(to_); } void StepRange::load(DumpLoad& a) { a.load(from_); a.load(to_); } //---------------------------------------------------------------------------------------------------------------------- } // namespace metkit::mars metkit-1.16.0/src/metkit/mars/StepRange.h000066400000000000000000000070121513171467200201720ustar00rootroot00000000000000/* * (C) Copyright 1996- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ // File StepRange.h // Baudouin Raoult - ECMWF Dec 97 #ifndef metkit_StepRange_H #define metkit_StepRange_H #include #include "eckit/persist/Bless.h" #include "eckit/types/Time.h" #include "eckit/types/Types.h" namespace eckit { class DumpLoad; } namespace metkit::mars { //---------------------------------------------------------------------------------------------------------------------- class StepRange { public: // -- Exceptions // None // -- Contructors StepRange(const std::string&); explicit StepRange(eckit::Time from = eckit::Time(0), eckit::Time to = eckit::Time(0)) : from_(from / 3600.), to_(to / 3600.) { if (from != eckit::Time(0) && to == eckit::Time(0)) { to_ = from_; } } explicit StepRange(double from, double to = 0) : StepRange(eckit::Time(std::lround(from * 3600.), true), eckit::Time(std::lround(to * 3600.), true)) {} #include "metkit/mars/StepRange.b" // -- Destructor ~StepRange() {} // -- Convertors // None // -- Operators // None operator std::string() const; std::string toString(bool useDays = false, bool alwaysUseHours = false) const; StepRange& operator+=(const eckit::Time& step) { from_ += step / 3600.; to_ += step / 3600.; return *this; } StepRange& operator-=(const eckit::Time& step) { from_ -= step / 3600.; to_ -= step / 3600.; return *this; } bool operator==(const StepRange& other) const { return from_ == other.from_ && to_ == other.to_; } bool operator!=(const StepRange& other) const { return from_ != other.from_ || to_ != other.to_; } bool operator<(const StepRange& other) const { return (from_ != other.from_) ? (from_ < other.from_) : (to_ < other.to_); } bool operator<=(const StepRange& other) const { return (from_ != other.from_) ? (from_ <= other.from_) : (to_ <= other.to_); } bool operator>(const StepRange& other) const { return other < *this; } // -- Methods double from() const { return from_; } double to() const { return to_; } void dump(eckit::DumpLoad&) const; void load(eckit::DumpLoad&); // -- Overridden methods // None // -- Class members // None // -- Class methods // None // Uncomment for persistent, remove otherwise protected: // -- Members // None // -- Methods void print(std::ostream& s, bool useDays = false, bool alwaysUseHours = false) const; // -- Overridden methods // None // -- Class members // None // -- Class methods // None private: // No copy allowed // -- Members double from_; double to_; // -- Methods // None // -- Overridden methods // None // -- Class members // None // -- Class methods // None // -- Friends friend std::ostream& operator<<(std::ostream& s, const StepRange& p) { p.print(s); return s; } }; //---------------------------------------------------------------------------------------------------------------------- } // namespace metkit::mars #endif metkit-1.16.0/src/metkit/mars/StepRangeNormalise.h000066400000000000000000000056171513171467200220550ustar00rootroot00000000000000/* * (C) Copyright 1996- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ /// @author Simon Smart /// @date May 2019 #ifndef metkit_StepRangeNormalise_H #define metkit_StepRangeNormalise_H #include #include "eckit/exception/Exceptions.h" #include "metkit/mars/StepRange.h" namespace metkit { namespace mars { //---------------------------------------------------------------------------------------------------------------------- // It would be nice to put this in StepRange (as is done with ParamID), but this seems // to break the generation of the StepRange.b file. // // -> Split it out class StepRangeNormalise { public: template static void normalise(std::vector& v, const AXIS_T& axis); }; //---------------------------------------------------------------------------------------------------------------------- template void StepRangeNormalise::normalise(std::vector& values, const AXIS_T& axis) { std::vector outputValues; for (eckit::Ordinal i = 0; i < values.size(); ++i) { // If the supplied range is found in the axis, then use that auto j = std::find(axis.begin(), axis.end(), values[i]); if (j != axis.end()) { outputValues.push_back(values[i]); // If specified, and matched, a RANGE, then use that if (values[i].from() != values[i].to()) { eckit::Log::info() << "Matched range: " << values[i] << std::endl; continue; } } bool matched = false; double singleValue = values[i].from(); if (values[i].from() != values[i].to()) { j = std::find(axis.begin(), axis.end(), StepRange(singleValue, singleValue)); if (j != axis.end()) { outputValues.push_back(*j); matched = true; } } // If singleValue == 0, this test is the same as the previous one... if (singleValue != 0) { j = std::find(axis.begin(), axis.end(), StepRange(0, singleValue)); if (j != axis.end()) { if (matched) { eckit::Log::userWarning() << "Step " << values[i] << " matches " << values[i] << " and " << (*j) << std::endl; } outputValues.push_back(*j); } } } std::swap(values, outputValues); } //---------------------------------------------------------------------------------------------------------------------- } // namespace mars } // namespace metkit #endif metkit-1.16.0/src/metkit/mars/Type.cc000066400000000000000000000277231513171467200173740ustar00rootroot00000000000000/* * (C) Copyright 1996- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ #include "metkit/mars/Type.h" #include #include #include #include #include #include #include #include #include #include #include "eckit/exception/Exceptions.h" #include "eckit/value/Value.h" #include "metkit/hypercube/HyperCube.h" #include "metkit/mars/ContextRule.h" #include "metkit/mars/MarsRequest.h" #include "metkit/mars/TypeToByList.h" namespace metkit::mars { //---------------------------------------------------------------------------------------------------------------------- void Context::add(std::unique_ptr rule) { rules_.push_back(std::move(rule)); } bool Context::matches(MarsRequest req) const { for (const auto& r : rules_) { if (!r->matches(req)) { return false; } } return true; } std::ostream& operator<<(std::ostream& s, const Context& c) { c.print(s); return s; } void Context::print(std::ostream& out) const { std::string sep; out << "Context["; for (const auto& r : rules_) { out << sep << *r; sep = ","; } out << "]"; } //---------------------------------------------------------------------------------------------------------------------- // HELPERS std::unique_ptr parseRule(std::string key, eckit::Value r) { std::set vals; if (r.isList()) { if (r.size() == 0) { throw eckit::UserError("Empty list for context rule '" + key + "'"); } bool exclude = (r[0] == "!"); for (size_t k = exclude ? 1 : 0; k < r.size(); k++) { vals.insert(r[k]); } if (exclude) return std::make_unique(key, vals); return std::make_unique(key, vals); } else { ASSERT(r.isString()); std::string v = r; if (v == "undefined") { return std::make_unique(key); } else if (v == "defined") { return std::make_unique(key); } } return nullptr; } std::unique_ptr Context::parseContext(eckit::Value c) { std::unique_ptr context = std::make_unique(); eckit::Value keys = c.keys(); for (size_t j = 0; j < keys.size(); j++) { std::string key = keys[j]; context->add(parseRule(key, c[key])); } return context; } size_t Context::maxAxisIndex() const { size_t maxIndex = 0; for (const auto& r : rules_) { size_t idx = 0; if (!r->key().empty() && r->key()[0] != '_') { idx = metkit::hypercube::AxisOrder::instance().index(r->key()); if (idx > maxIndex) { maxIndex = idx; } } } return maxIndex; } //---------------------------------------------------------------------------------------------------------------------- Type::Type(const std::string& name, const eckit::Value& settings) : name_(name), flatten_(true), multiple_(false), duplicates_(true) { if (settings.contains("multiple")) { multiple_ = settings["multiple"]; } if (settings.contains("flatten")) { flatten_ = settings["flatten"]; } if (settings.contains("duplicates")) { duplicates_ = settings["duplicates"]; } if (settings.contains("category")) { category_ = std::string(settings["category"]); } if (settings.contains("defaults")) { eckit::Value defaults = settings["defaults"]; if (!defaults.isNil() && defaults.isList()) { for (size_t i = 0; i < defaults.size(); i++) { std::vector vals; eckit::Value d = defaults[i]; ASSERT(d.contains("vals")); eckit::Value vv = d["vals"]; if (vv.isList()) { for (size_t k = 0; k < vv.size(); k++) { vals.push_back(vv[k]); } } else { vals.push_back(vv); } if (d.contains("context")) { defaults_.emplace(Context::parseContext(d["context"]), vals); } else { defaults_.emplace(std::make_unique(), vals); } } } } } void Type::defaults(std::shared_ptr context, const std::vector& values) { defaults_.emplace(std::move(context), values); } void Type::set(std::shared_ptr context, const std::vector& values) { sets_.emplace(std::move(context), values); } void Type::unset(std::shared_ptr context) { unsets_.insert(std::move(context)); } void Type::patchRequest(MarsRequest& request, const std::vector& values) { // Special case: inheritance from another key. // If the value is of the form _key, then copy values from that key if (values.size() == 1 && values[0][0] == '_') { std::string key = values[0].substr(1); if (request.has(key)) { request.setValuesTyped(this, request.values(key)); } } else { request.setValuesTyped(this, values); } } bool Type::flatten() const { return flatten_; } bool Type::multiple() const { return multiple_; } size_t Type::count(const std::vector& values) const { return flatten_ ? values.size() : 1; } class NotInSet { std::set set_; public: NotInSet(const std::vector& f) : set_(f.begin(), f.end()) {} bool operator()(const std::string& s) const { return set_.find(s) == set_.end(); } }; bool Type::filter(const std::vector& filter, std::vector& values) const { NotInSet not_in_set(filter); values.erase(std::remove_if(values.begin(), values.end(), not_in_set), values.end()); return !values.empty(); } bool Type::filter(const std::string& keyword, const std::vector& f, std::vector& values) const { if (keyword == name_) { return filter(f, values); } auto it = filters_.find(keyword); if (it == filters_.end()) { return false; } return it->second(f, values); } class InSet { std::set set_; public: InSet(const std::vector& f) : set_(f.begin(), f.end()) {} bool operator()(const std::string& s) const { return set_.find(s) != set_.end(); } }; bool Type::matches(const std::vector& match, const std::vector& values) const { InSet in_set(match); return std::find_if(values.begin(), values.end(), in_set) != values.end(); } std::ostream& operator<<(std::ostream& s, const Type& x) { x.print(s); return s; } std::string Type::tidy(const std::string& value, const MarsRequest& request) const { std::string result = value; expand(result, request); return result; } bool Type::expand(std::string& value, const MarsRequest&) const { std::ostringstream oss; oss << *this << ": expand not implemented (" << value << ")"; throw eckit::SeriousBug(oss.str()); } bool Type::expand(const MarsExpandContext&, std::string& value, const MarsRequest& request) const { return expand(value, request); } void Type::expand(std::vector& values, const MarsRequest& request) const { if (toByList_ && values.size() > 1) { toByList_->expandRanges(values, request); } std::vector newvals; std::set seen; for (std::string& val : values) { std::string value = val; if (!expand(value, request)) { std::ostringstream oss; oss << *this << ": cannot expand '" << val << "'"; throw eckit::UserError(oss.str()); } if (hasGroups()) { auto gg = group(value); if (gg) { for (const auto& v : gg->get()) { if (seen.find(v) == seen.end()) { seen.insert(v); newvals.push_back(v); } } } } else { if (!duplicates_ && seen.find(value) != seen.end()) { std::ostringstream oss; oss << *this << ": duplicated value '" << value << "'"; throw eckit::UserError(oss.str()); } newvals.push_back(value); } } std::swap(newvals, values); if (!multiple_ && values.size() > 1) { throw eckit::UserError("Only one value possible for '" + name_ + "'"); } } void Type::setDefaults(MarsRequest& request) { if (inheritance_) { request.setValuesTyped(this, inheritance_.value()); } else { bool unset = false; for (const auto& unsetContext : unsets_) { if (unsetContext->matches(request)) { unset = true; break; } } if (!unset) { for (const auto& [defaultContext, values] : defaults_) { if (defaultContext->matches(request)) { patchRequest(request, values); break; } } } } } void Type::setInheritance(const std::vector& inheritance) { inheritance_ = inheritance; } const std::vector& Type::flattenValues(const MarsRequest& request) { return request.values(name_); } void Type::clearDefaults() { defaults_.clear(); } void Type::reset() { inheritance_.reset(); } const std::string& Type::name() const { return name_; } const std::string& Type::category() const { return category_; } void Type::pass2(MarsRequest& request) {} void Type::finalise(MarsRequest& request, bool strict) { const std::vector& values = request.values(name_, true); if (values.size() == 1 && values[0] == "off") { request.unsetValues(name_); } else { if (values.size() > 0) { for (const auto& context : unsets_) { if (context->matches(request)) { if (strict && request.has(name_)) { std::ostringstream oss; oss << *this << ": Key [" << name_ << "] not acceptable with context: " << *context; throw eckit::UserError(oss.str()); } request.unsetValues(name_); } } } if (request.verb() != "list") { for (const auto& [context, values] : sets_) { if (context->matches(request)) { if (strict && !request.has(name_)) { std::ostringstream oss; oss << *this << ": missing Key [" << name_ << "] - required with context: " << *context; throw eckit::UserError(oss.str()); } patchRequest(request, values); } } } } } void Type::check(const std::vector& values) const { if (flatten_) { std::set s(values.begin(), values.end()); if (values.size() != s.size()) { std::cerr << "Duplicate values in " << name_ << " " << values; std::set seen; for (const std::string& val : values) { if (seen.find(val) != seen.end()) { std::cerr << ' ' << val; } seen.insert(val); } std::cerr << std::endl; } } } //---------------------------------------------------------------------------------------------------------------------- } // namespace metkit::mars metkit-1.16.0/src/metkit/mars/Type.h000066400000000000000000000202711513171467200172250ustar00rootroot00000000000000/* * (C) Copyright 1996- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ /// @file Type.h /// @author Baudouin Raoult /// @author Tiago Quintino /// @author Emanuele Danovaro /// @date April 2016 #pragma once #include #include #include #include #include #include #include "eckit/memory/Counted.h" #include "eckit/value/Value.h" #include "metkit/mars/MarsRequest.h" namespace metkit::mars { class MarsExpandContext; //---------------------------------------------------------------------------------------------------------------------- /// @brief abstract class - ContextRule subclasses are used to define a context. A MarsRequest matches a context, if it /// matches all its ContextRules class ContextRule { public: ContextRule(const std::string& k) : key_(k) {} virtual ~ContextRule() = default; const std::string& key() const { return key_; } virtual bool matches(MarsRequest req) const = 0; friend std::ostream& operator<<(std::ostream& s, const ContextRule& r) { r.print(s); return s; } protected: std::string key_; private: // methods virtual void print(std::ostream& out) const = 0; }; //---------------------------------------------------------------------------------------------------------------------- /// @brief A MarsRequest matches an Include ContextRule if at least one of the mars request values matches with the /// values associated with the Include rule class Include : public ContextRule { public: Include(const std::string& k, const std::set& vv) : ContextRule(k), vals_(vv) {} bool matches(MarsRequest req) const override { if (key_ == "_verb") { return (vals_.find(req.verb()) != vals_.end()); } if (!req.has(key_)) { return false; } for (const std::string& v : req.values(key_)) { if (vals_.find(v) != vals_.end()) { return true; } } return false; } private: // methods void print(std::ostream& out) const override { out << "Include[key=" << key_ << ",vals=[" << vals_ << "]]"; } private: std::set vals_; }; /// @brief A MarsRequest matches an Exclude ContextRule if none of the mars request values matches with the values /// associated with the Exclude rule class Exclude : public ContextRule { public: Exclude(const std::string& k, const std::set& vv) : ContextRule(k), vals_(vv) {} bool matches(MarsRequest req) const override { if (!req.has(key_)) { return false; } for (const std::string& v : req.values(key_)) { if (vals_.find(v) != vals_.end()) { return false; } } return true; } private: // methods void print(std::ostream& out) const override { out << "Exclude[key=" << key_ << ",vals=[" << vals_ << "]]"; } private: std::set vals_; }; /// @brief A MarsRequest matches an Undef ContextRule if the specified keyword is not defined in the mars request class Undef : public ContextRule { public: Undef(const std::string& k) : ContextRule(k) {} bool matches(MarsRequest req) const override { return !req.has(key_); } private: // methods void print(std::ostream& out) const override { out << "Undef[key=" << key_ << "]"; } }; /// @brief A MarsRequest matches an Undef ContextRule if the specified keyword is defined in the mars request class Def : public ContextRule { public: Def(const std::string& k) : ContextRule(k) {} bool matches(MarsRequest req) const override { return req.has(key_); } private: // methods void print(std::ostream& out) const override { out << "Def[key=" << key_ << "]"; } }; //---------------------------------------------------------------------------------------------------------------------- /// @brief a Context contains a list of ContextRule. A MarsRequest matches a context, if it matches all the ContextRules /// associated class Context { public: static std::unique_ptr parseContext(eckit::Value c); /// @note takes ownership of the rule void add(std::unique_ptr rule); size_t maxAxisIndex() const; bool matches(MarsRequest req) const; friend std::ostream& operator<<(std::ostream& s, const Context& x); private: // methods void print(std::ostream& out) const; private: std::vector> rules_; }; //---------------------------------------------------------------------------------------------------------------------- class ITypeToByList { public: virtual ~ITypeToByList() = default; virtual void expandRanges(std::vector& values, const MarsRequest& request) const = 0; }; //---------------------------------------------------------------------------------------------------------------------- class Type : public eckit::Counted { public: // methods Type(const std::string& name, const eckit::Value& settings); ~Type() noexcept override = default; virtual bool expand(std::string& value, const MarsRequest& request = {}) const; [[deprecated]] bool expand(const MarsExpandContext& ctx, std::string& value, const MarsRequest& request = {}) const; void expand(std::vector& values, const MarsRequest& request = {}) const; std::string tidy(const std::string& value, const MarsRequest& request = {}) const; virtual void setDefaults(MarsRequest& request); virtual void setInheritance(const std::vector& inheritance); virtual void check(const std::vector& values) const; virtual void clearDefaults(); virtual void reset(); virtual void pass2(MarsRequest& request); virtual void finalise(MarsRequest& request, bool strict); virtual const std::vector& flattenValues(const MarsRequest& request); virtual bool flatten() const; virtual bool multiple() const; virtual bool filter(const std::vector& filter, std::vector& values) const; virtual bool filter(const std::string& keyword, const std::vector& filter, std::vector& values) const; virtual bool matches(const std::vector& filter, const std::vector& values) const; const std::string& name() const; const std::string& category() const; friend std::ostream& operator<<(std::ostream& s, const Type& x); virtual size_t count(const std::vector& values) const; protected: // methods virtual bool hasGroups() const { return false; } virtual std::optional>> group(const std::string&) const { NOTIMP; } friend class MarsLanguage; void defaults(std::shared_ptr context, const std::vector& values); void set(std::shared_ptr context, const std::vector& values); void unset(std::shared_ptr context); protected: // members std::string name_; std::string category_; bool flatten_; bool multiple_; bool duplicates_; std::map, std::vector> defaults_; std::map, std::vector> sets_; std::set> unsets_; std::optional> inheritance_; std::unique_ptr toByList_; std::map&, std::vector&)>> filters_; private: // methods virtual void print(std::ostream& out) const = 0; void patchRequest(MarsRequest& request, const std::vector& values); }; //---------------------------------------------------------------------------------------------------------------------- } // namespace metkit::mars metkit-1.16.0/src/metkit/mars/TypeAny.cc000066400000000000000000000020721513171467200200320ustar00rootroot00000000000000/* * (C) Copyright 1996- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ #include "metkit/mars/TypeAny.h" #include "metkit/mars/TypesFactory.h" namespace metkit::mars { //---------------------------------------------------------------------------------------------------------------------- TypeAny::TypeAny(const std::string& name, const eckit::Value& settings) : Type(name, settings) {} void TypeAny::print(std::ostream& out) const { out << "TypeAny[name=" << name_ << "]"; } bool TypeAny::expand(std::string&, const MarsRequest&) const { return true; } static TypeBuilder type("any"); //---------------------------------------------------------------------------------------------------------------------- } // namespace metkit::mars metkit-1.16.0/src/metkit/mars/TypeAny.h000066400000000000000000000022301513171467200176700ustar00rootroot00000000000000/* * (C) Copyright 1996- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ /// @file TypeAny.h /// @author Baudouin Raoult /// @author Tiago Quintino /// @date April 2016 #pragma once #include "metkit/mars/Type.h" namespace metkit::mars { //---------------------------------------------------------------------------------------------------------------------- class TypeAny : public Type { public: // methods TypeAny(const std::string& name, const eckit::Value& settings = eckit::Value()); ~TypeAny() noexcept override = default; private: // methods void print(std::ostream& out) const override; bool expand(std::string& value, const MarsRequest& request) const override; }; //---------------------------------------------------------------------------------------------------------------------- } // namespace metkit::mars metkit-1.16.0/src/metkit/mars/TypeDate.cc000066400000000000000000000133061513171467200201620ustar00rootroot00000000000000/* * (C) Copyright 1996- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ #include "metkit/mars/TypeDate.h" #include #include #include #include "eckit/types/Date.h" #include "eckit/utils/StringTools.h" #include "eckit/utils/Tokenizer.h" #include "eckit/utils/Translator.h" #include "metkit/mars/MarsRequest.h" #include "metkit/mars/TypeToByList.h" #include "metkit/mars/TypesFactory.h" namespace { //---------------------------------------------------------------------------------------------------------------------- static std::array months{"jan", "feb", "mar", "apr", "may", "jun", "jul", "aug", "sep", "oct", "nov", "dec"}; std::string month(const std::string& value) { if (std::isdigit(value[0])) { eckit::Translator s2i; int m = s2i(value); if (m > 12) { std::ostringstream oss; oss << value << " is not a valid month"; throw eckit::BadValue(oss.str()); } return months[m - 1]; } ASSERT(value.size() >= 3); const auto* it = std::find(months.begin(), months.end(), eckit::StringTools::lower(value.substr(0, 3))); if (it == months.end()) { std::ostringstream oss; oss << value << " is not a valid month name"; throw eckit::BadValue(oss.str()); } return *it; } long day(std::string& value) { if (value.empty()) { return -1; } eckit::Translator s2l; if (value[0] == '0' || value[0] == '-') { long n = s2l(value); if (n <= 0) { eckit::Date now(n); return now.day(); } } else { eckit::Tokenizer t("-"); std::vector tokens = t.tokenize(value); if (tokens.size() == 2) { if (std::isdigit(tokens[0][0]) && tokens[0].size() > 2) { // year-dayOfYear (e.g. 2018-23 ==> 20180123) eckit::Date d(s2l(tokens[0]), s2l(tokens[1])); return d.day(); } else { // month-day (i.e. TypeClimateDaily) return s2l(tokens[1]); } } if (tokens.size() == 1 && (!std::isdigit(value[0]) || value.size() <= 2)) { // month (i.e. TypeClimateMonthly) return -1; } eckit::Date date(value); return date.day(); } return -1; } bool filterByDay(const std::vector& filter, std::vector& values) { std::set days; eckit::Translator s2l; for (auto f : filter) { days.emplace(s2l(f)); } for (auto v = values.begin(); v != values.end();) { long d = day(*v); if (d != -1) { auto it = days.find(d); if (it != days.end()) { v++; continue; } } v = values.erase(v); } return !values.empty(); } } // namespace namespace metkit::mars { //---------------------------------------------------------------------------------------------------------------------- TypeDate::TypeDate(const std::string& name, const eckit::Value& settings) : Type(name, settings) { toByList_ = std::make_unique>(*this, settings); multiple_ = true; filters_["day"] = &filterByDay; } void TypeDate::pass2(MarsRequest& request) { std::vector values = request.values(name_, true); if (values.size() == 1 && values[0] == "-1") { Type::expand(values, request); request.setValuesTyped(this, values); } } bool TypeDate::expand(std::string& value, const MarsRequest&) const { if (!value.empty()) { eckit::Translator s2l; eckit::Translator l2s; if (value[0] == '0' || value[0] == '-') { long n = s2l(value); if (n <= 0) { eckit::Date now(n); value = l2s(now.yyyymmdd()); } } else { eckit::Tokenizer t("-"); std::vector tokens = t.tokenize(value); if (tokens.size() == 2) { // month-day (i.e. TypeClimateDaily) if (std::isdigit(tokens[0][0]) && tokens[0].size() > 2) { // year-dayOfYear (e.g. 2018-23 ==> 20180123) eckit::Date d(s2l(tokens[0]), s2l(tokens[1])); value = l2s(d.yyyymmdd()); } else { // month-day (i.e. TypeClimateDaily) std::string m = month(tokens[0]); long d = s2l(tokens[1]); value = m + "-" + l2s(d); } } else { if (tokens.size() == 1 && (!std::isdigit(value[0]) || value.size() <= 2)) { // month (i.e. TypeClimateMonthly) value = month(tokens[0]); } else { eckit::Date date(value); value = l2s(date.yyyymmdd()); } } } } return true; } void TypeDate::print(std::ostream& out) const { out << "TypeDate[name=" << name_ << "]"; } static TypeBuilder type("date"); //---------------------------------------------------------------------------------------------------------------------- } // namespace metkit::mars metkit-1.16.0/src/metkit/mars/TypeDate.h000066400000000000000000000023311513171467200200200ustar00rootroot00000000000000/* * (C) Copyright 1996- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ /// @file TypeDate.h /// @author Baudouin Raoult /// @author Tiago Quintino /// @author Emanuele Danovaro /// @date April 2016 #pragma once #include "metkit/mars/Type.h" namespace metkit::mars { //---------------------------------------------------------------------------------------------------------------------- class TypeDate : public Type { public: // methods TypeDate(const std::string& name, const eckit::Value& settings); ~TypeDate() noexcept override = default; private: // methods void print(std::ostream& out) const override; void pass2(MarsRequest& request) override; bool expand(std::string& value, const MarsRequest& request) const override; }; //---------------------------------------------------------------------------------------------------------------------- } // namespace metkit::mars metkit-1.16.0/src/metkit/mars/TypeEnum.cc000066400000000000000000000110121513171467200202010ustar00rootroot00000000000000/* * (C) Copyright 1996- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ #include "metkit/mars/TypeEnum.h" #include "eckit/utils/StringTools.h" #include "metkit/config/LibMetkit.h" #include "metkit/mars/MarsLanguage.h" #include "metkit/mars/TypesFactory.h" namespace metkit::mars { //---------------------------------------------------------------------------------------------------------------------- void TypeEnum::addValue(const std::string& vv, uint16_t idx, bool allowDuplicates) const { std::string value = eckit::StringTools::lower(vv); if (!allowDuplicates && values_.find(value) != values_.end()) { std::ostringstream oss; oss << "Redefined enum value '" << value << "'"; throw eckit::SeriousBug(oss.str()); } values_[value] = idx; } uint16_t TypeEnum::parseValueNames(const eckit::Value& names, bool allowDuplicates) const { std::string firstName = names.isList() ? names[0] : names; uint16_t idx = groups_.size(); addValue(firstName, idx, allowDuplicates); if (names.isList()) { for (size_t i = 1; i < names.size(); ++i) { addValue(names[i], idx, allowDuplicates); } } if (uppercase_) { firstName = eckit::StringTools::upper(firstName); } groups_.emplace_back(firstName, std::vector{}); return idx; } std::vector TypeEnum::parseEnumValue(const eckit::Value& val, bool allowDuplicates) const { if (val.isMap()) { hasGroups_ = true; ASSERT(val.contains("name")); uint16_t idx = parseValueNames(val["name"], allowDuplicates); ASSERT(val.contains("group")); eckit::Value group = val["group"]; ASSERT(group.isList()); std::set outSet; for (size_t i = 0; i < group.size(); ++i) { std::vector groupVals = parseEnumValue(group[i], true); for (const auto& v : groupVals) { if (outSet.find(v) == outSet.end()) { outSet.insert(v); groups_.at(idx).second.push_back(v); } } } return groups_.at(idx).second; } uint16_t idx = parseValueNames(val, allowDuplicates); std::string nn = groups_.at(idx).first; groups_.at(idx).second.push_back(nn); return {nn}; } void TypeEnum::readValuesFile() const { if (!valuesFile_.empty()) { auto values = MarsLanguage::jsonFile(valuesFile_); ASSERT(values.isList()); for (size_t i = 0; i < values.size(); ++i) { parseEnumValue(values[i]); } } } TypeEnum::TypeEnum(const std::string& name, const eckit::Value& settings) : Type(name, settings) { LOG_DEBUG_LIB(LibMetkit) << "TypeEnum name=" << name << " settings=" << settings << std::endl; eckit::Value values = settings["values"]; if (settings.contains("uppercase")) { uppercase_ = settings["uppercase"]; } if (!values.isList()) { valuesFile_ = static_cast(values); } else { for (size_t i = 0; i < values.size(); ++i) { parseEnumValue(values[i]); } } } void TypeEnum::print(std::ostream& out) const { out << "TypeEnum[name=" << name_ << "]"; } bool TypeEnum::expand(std::string& value, const MarsRequest& request) const { auto it = find(value); if (it == values_.end()) { return false; } ASSERT(groups_.size() > it->second); value = groups_.at(it->second).first; return true; } std::map::const_iterator TypeEnum::find(const std::string& value) const { std::call_once(readValues_, &TypeEnum::readValuesFile, this); return values_.find(eckit::StringTools::lower(value)); } std::optional>> TypeEnum::group(const std::string& value) const { ASSERT(hasGroups_); auto it = find(value); if (it != values_.end()) { return groups_.at(it->second).second; } return std::nullopt; } void TypeEnum::reset() { Type::reset(); } static TypeBuilder type("enum"); //---------------------------------------------------------------------------------------------------------------------- } // namespace metkit::mars metkit-1.16.0/src/metkit/mars/TypeEnum.h000066400000000000000000000041551513171467200200550ustar00rootroot00000000000000/* * (C) Copyright 1996- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ /// @file TypeEnum.h /// @author Baudouin Raoult /// @author Tiago Quintino /// @date April 2016 #pragma once #include #include "metkit/mars/Type.h" namespace metkit::mars { //---------------------------------------------------------------------------------------------------------------------- class TypeEnum : public Type { public: // methods TypeEnum(const std::string& name, const eckit::Value& settings); ~TypeEnum() noexcept override = default; private: // methods bool hasGroups() const override { return hasGroups_; } std::optional>> group( const std::string& value) const override; void print(std::ostream& out) const override; void reset() override; bool expand(std::string& value, const MarsRequest& request) const override; std::map::const_iterator find(const std::string& value) const; std::vector parseEnumValue(const eckit::Value& val, bool allowDuplicates = false) const; void addValue(const std::string& value, uint16_t idx, bool allowDuplicates) const; uint16_t parseValueNames(const eckit::Value& names, bool allowDuplicates) const; void readValuesFile() const; private: // members std::string valuesFile_; bool uppercase_ = false; mutable bool hasGroups_ = false; mutable std::vector>> groups_; mutable std::map values_; // map of acceptable values (included aliases) mutable std::once_flag readValues_; }; //---------------------------------------------------------------------------------------------------------------------- } // namespace metkit::mars metkit-1.16.0/src/metkit/mars/TypeExpver.cc000066400000000000000000000027771513171467200205700ustar00rootroot00000000000000/* * (C) Copyright 1996- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ #include #include "eckit/utils/StringTools.h" #include "eckit/utils/Translator.h" #include "metkit/mars/TypeExpver.h" #include "metkit/mars/TypesFactory.h" namespace metkit { namespace mars { //---------------------------------------------------------------------------------------------------------------------- TypeExpver::TypeExpver(const std::string& name, const eckit::Value& settings) : Type(name, settings) {} bool TypeExpver::expand(std::string& value, const MarsRequest&) const { std::string v = eckit::StringTools::lower(eckit::StringTools::trim(value)); if (v == "all" || v == "any") { value = v; } else { std::ostringstream oss; oss << std::setfill('0') << std::setw(4) << eckit::StringTools::trim(value); value = oss.str(); } return true; } void TypeExpver::print(std::ostream& out) const { out << "TypeExpver[name=" << name_ << "]"; } static TypeBuilder type("expver"); //---------------------------------------------------------------------------------------------------------------------- } // namespace mars } // namespace metkit metkit-1.16.0/src/metkit/mars/TypeExpver.h000066400000000000000000000022241513171467200204150ustar00rootroot00000000000000/* * (C) Copyright 1996- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ /// @file TypeExpver.h /// @author Baudouin Raoult /// @author Tiago Quintino /// @date April 2016 #pragma once #include "metkit/mars/Type.h" namespace metkit::mars { //---------------------------------------------------------------------------------------------------------------------- class TypeExpver : public Type { public: // methods TypeExpver(const std::string& name, const eckit::Value& settings); ~TypeExpver() noexcept override = default; bool expand(std::string& value, const MarsRequest& request) const override; private: // methods void print(std::ostream& out) const override; }; //---------------------------------------------------------------------------------------------------------------------- } // namespace metkit::mars metkit-1.16.0/src/metkit/mars/TypeFloat.cc000066400000000000000000000053751513171467200203610ustar00rootroot00000000000000/* * (C) Copyright 1996- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ #include "eckit/utils/Translator.h" #include "metkit/mars/MarsRequest.h" #include "metkit/mars/TypeFloat.h" #include "metkit/mars/TypeToByList.h" #include "metkit/mars/TypesFactory.h" namespace metkit::mars { //---------------------------------------------------------------------------------------------------------------------- TypeFloat::TypeFloat(const std::string& name, const eckit::Value& settings) : Type(name, settings) {} bool TypeFloat::expand(std::string& value, const MarsRequest&) const { bool dot = false; for (std::string::const_iterator j = value.begin(); j != value.end(); ++j) { switch (*j) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case '-': break; case '.': dot = true; break; default: return false; } } // Strip leading zeros while (value.size() && value[0] == '0') { value = value.substr(1); } // Strip trailing zeros if (dot) { while (value.size() && value[value.size() - 1] == '0') { value = value.substr(0, value.size() - 1); } if (value.size() && value[value.size() - 1] == '.') { value = value.substr(0, value.size() - 1); } } if (value.empty()) { value = "0"; } return true; } void TypeFloat::print(std::ostream& out) const { out << "TypeFloat[name=" << name() << "]"; } static TypeBuilder type("float"); //---------------------------------------------------------------------------------------------------------------------- class TypeToByListFloat : public TypeFloat { public: TypeToByListFloat(const std::string& name, const eckit::Value& settings) : TypeFloat(name, settings) { toByList_ = std::make_unique>(*this, settings); multiple_ = true; } protected: void print(std::ostream& out) const override { out << "TypeToByListFloat[name=" << name() << "]"; } }; static TypeBuilder typeList("to-by-list-float"); //---------------------------------------------------------------------------------------------------------------------- } // namespace metkit::mars metkit-1.16.0/src/metkit/mars/TypeFloat.h000066400000000000000000000022561513171467200202160ustar00rootroot00000000000000/* * (C) Copyright 1996- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ /// @file TypeFloat.h /// @author Baudouin Raoult /// @author Tiago Quintino /// @author Emanuele Danovaro /// @date April 2016 #pragma once #include "metkit/mars/Type.h" namespace metkit::mars { //---------------------------------------------------------------------------------------------------------------------- class TypeFloat : public Type { public: // methods TypeFloat(const std::string& name, const eckit::Value& settings); ~TypeFloat() noexcept override = default; private: // methods void print(std::ostream& out) const override; bool expand(std::string& value, const MarsRequest& request) const override; }; //---------------------------------------------------------------------------------------------------------------------- } // namespace metkit::mars metkit-1.16.0/src/metkit/mars/TypeInteger.cc000066400000000000000000000057121513171467200207040ustar00rootroot00000000000000/* * (C) Copyright 1996- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ #include "eckit/utils/Translator.h" #include "metkit/mars/MarsRequest.h" #include "metkit/mars/TypeInteger.h" #include "metkit/mars/TypeToByList.h" #include "metkit/mars/TypesFactory.h" namespace metkit::mars { //---------------------------------------------------------------------------------------------------------------------- TypeInteger::TypeInteger(const std::string& name, const eckit::Value& settings) : Type(name, settings) { // check if the settings contain a range if (settings.contains("range") && settings["range"].size() == 2) { range_ = {settings["range"][0], settings["range"][1]}; } } void TypeInteger::print(std::ostream& out) const { out << "TypeInteger[name=" << name() << "]"; } bool TypeInteger::ok(const std::string& value, long& n) const { n = 0; long sign = 1; for (std::string::const_iterator j = value.begin(); j != value.end(); ++j) { switch (*j) { case '-': if (j == value.begin()) { sign = -1; } else { return false; } break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': n *= 10; n += (*j) - '0'; break; default: return false; } } n *= sign; return !range_ || (n >= range_->lower_ && n <= range_->upper_); } bool TypeInteger::expand(std::string& value, const MarsRequest&) const { long n = 0; if (ok(value, n)) { static eckit::Translator l2s; value = l2s(n); return true; } return false; } static TypeBuilder type("integer"); //---------------------------------------------------------------------------------------------------------------------- class TypeToByListInt : public TypeInteger { public: TypeToByListInt(const std::string& name, const eckit::Value& settings) : TypeInteger(name, settings) { toByList_ = std::make_unique>(*this, settings); multiple_ = true; } protected: void print(std::ostream& out) const override { out << "TypeToByListInt[name=" << name() << "]"; } }; static TypeBuilder typeList("to-by-list"); //---------------------------------------------------------------------------------------------------------------------- } // namespace metkit::mars metkit-1.16.0/src/metkit/mars/TypeInteger.h000066400000000000000000000025521513171467200205450ustar00rootroot00000000000000/* * (C) Copyright 1996- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ /// @file TypeInteger.h /// @author Baudouin Raoult /// @author Tiago Quintino /// @author Emanuele Danovaro /// @date April 2016 #pragma once #include #include #include "metkit/mars/Type.h" namespace metkit::mars { //---------------------------------------------------------------------------------------------------------------------- class TypeInteger : public Type { public: // methods TypeInteger(const std::string& name, const eckit::Value& settings); protected: bool ok(const std::string& value, long& n) const; bool expand(std::string& value, const MarsRequest& request) const override; private: // methods void print(std::ostream& out) const override; private: // members struct Range { int lower_; int upper_; }; std::optional range_; }; //---------------------------------------------------------------------------------------------------------------------- } // namespace metkit::mars metkit-1.16.0/src/metkit/mars/TypeLowercase.cc000066400000000000000000000023761513171467200212360ustar00rootroot00000000000000/* * (C) Copyright 1996- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ #include "eckit/utils/StringTools.h" #include "metkit/mars/TypeLowercase.h" #include "metkit/mars/TypesFactory.h" #include #include #include namespace metkit::mars { //---------------------------------------------------------------------------------------------------------------------- TypeLowercase::TypeLowercase(const std::string& name, const eckit::Value& settings) : Type(name, settings) {} void TypeLowercase::print(std::ostream& out) const { out << "TypeLowercase[name=" << name_ << "]"; } bool TypeLowercase::expand(std::string& value, const MarsRequest&) const { value = eckit::StringTools::lower(value); return true; } static TypeBuilder type("lowercase"); //---------------------------------------------------------------------------------------------------------------------- } // namespace metkit::mars metkit-1.16.0/src/metkit/mars/TypeLowercase.h000066400000000000000000000022321513171467200210670ustar00rootroot00000000000000/* * (C) Copyright 1996- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ /// @file TypeLowercase.h /// @author Emanuele Danovaro /// @date February 2024 #pragma once #include "metkit/mars/Type.h" namespace metkit::mars { //---------------------------------------------------------------------------------------------------------------------- class TypeLowercase : public Type { public: // methods TypeLowercase(const std::string& name, const eckit::Value& settings = eckit::Value()); ~TypeLowercase() noexcept override = default; private: // methods void print(std::ostream& out) const override; bool expand(std::string& value, const MarsRequest& request) const override; }; //---------------------------------------------------------------------------------------------------------------------- } // namespace metkit::mars metkit-1.16.0/src/metkit/mars/TypeMixed.cc000066400000000000000000000051221513171467200203500ustar00rootroot00000000000000/* * (C) Copyright 1996- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ #include "metkit/mars/TypeMixed.h" #include "metkit/mars/MarsRequest.h" #include "metkit/mars/TypesFactory.h" namespace metkit { namespace mars { //---------------------------------------------------------------------------------------------------------------------- TypeMixed::TypeMixed(const std::string& name, const eckit::Value& settings) : Type(name, settings) { eckit::Value types = settings["type"]; eckit::Value cfg; for (size_t i = 0; i < types.size(); ++i) { if (types[i].isString()) { cfg = settings; cfg["type"] = types[i]; Type* k = TypesFactory::build(name + "." + std::string(types[i]), cfg); k->attach(); types_.emplace_back(nullptr, k); } else { // it is a subtype, potentially with a Context cfg = types[i]; eckit::Value type = cfg["type"]; std::unique_ptr c; if (cfg.contains("context")) { c = Context::parseContext(cfg["context"]); } Type* k = TypesFactory::build(name + "." + std::to_string(i) + "." + std::string(type), cfg); k->attach(); types_.emplace_back(std::move(c), k); } } } TypeMixed::~TypeMixed() noexcept { for (auto it = types_.begin(); it != types_.end(); it++) { (*it).second->detach(); } } void TypeMixed::print(std::ostream& out) const { out << "TypeMixed[name=" << name_; for (auto it = types_.begin(); it != types_.end(); it++) { out << "," << *((*it).second); } out << "]"; } bool TypeMixed::expand(std::string& value, const MarsRequest& request) const { for (auto it = types_.begin(); it != types_.end(); it++) { if ((*it).first == nullptr || (*it).first->matches(request)) { std::string tmp = value; if ((*it).second->expand(tmp, request)) { value = tmp; return true; } } } return false; } static TypeBuilder type("mixed"); //---------------------------------------------------------------------------------------------------------------------- } // namespace mars } // namespace metkit metkit-1.16.0/src/metkit/mars/TypeMixed.h000066400000000000000000000024261513171467200202160ustar00rootroot00000000000000/* * (C) Copyright 1996- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ /// @file TypeMixed.h /// @author Baudouin Raoult /// @author Tiago Quintino /// @date April 2016 #ifndef metkit_TypeMixed_H #define metkit_TypeMixed_H #include "metkit/mars/Type.h" namespace metkit { namespace mars { //---------------------------------------------------------------------------------------------------------------------- class TypeMixed : public Type { public: // methods TypeMixed(const std::string& name, const eckit::Value& settings); ~TypeMixed() noexcept override; private: // methods void print(std::ostream& out) const override; bool expand(std::string& value, const MarsRequest& request) const override; std::vector, Type*>> types_; }; //---------------------------------------------------------------------------------------------------------------------- } // namespace mars } // namespace metkit #endif metkit-1.16.0/src/metkit/mars/TypeParam.cc000066400000000000000000000353761513171467200203600ustar00rootroot00000000000000/* * (C) Copyright 1996- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ #include "metkit/mars/TypeParam.h" #include "eckit/config/Resource.h" #include "eckit/log/Log.h" #include "eckit/parser/YAMLParser.h" #include "eckit/thread/AutoLock.h" #include "eckit/types/Types.h" #include "metkit/config/LibMetkit.h" #include "metkit/mars/MarsLanguage.h" #include "metkit/mars/TypesFactory.h" using eckit::Log; using metkit::LibMetkit; namespace { static eckit::Mutex* local_mutex = 0; static pthread_once_t once = PTHREAD_ONCE_INIT; class Matcher { std::string name_; eckit::Value values_; public: Matcher(const std::string& name, const eckit::Value values); bool match(const metkit::mars::MarsRequest& request, bool partial = false) const; friend std::ostream& operator<<(std::ostream& out, const Matcher& matcher) { out << matcher.name_ << "=" << matcher.values_; return out; } }; Matcher::Matcher(const std::string& name, const eckit::Value values) : name_(name), values_(values) { if (!values_.isList()) { values_ = eckit::Value::makeList(values_); } } bool Matcher::match(const metkit::mars::MarsRequest& request, bool partial) const { std::vector vals = request.values(name_, true); if (vals.size() == 0) { return partial; } for (size_t i = 0; i < values_.size(); i++) { std::string v = values_[i]; if (v == vals[0]) { return true; } } return false; } //---------------------------------------------------------------------------------------------------------------------- class Rule { std::vector matchers_; std::vector values_; mutable std::map mapping_; static std::vector defaultValues_; static std::map defaultMapping_; public: bool match(const metkit::mars::MarsRequest& request, bool partial = false) const; std::string lookup(const std::string& s, bool fail) const; long toParamid(const std::string& param) const; Rule(const eckit::Value& matchers, const eckit::Value& setters, const eckit::Value& ids); static void setDefault(const eckit::Value& setters, const eckit::Value& ids); void print(std::ostream& out) const { out << "{"; const char* sep = ""; for (std::vector::const_iterator j = matchers_.begin(); j != matchers_.end(); ++j) { out << sep << (*j); sep = ","; } out << "}"; } friend std::ostream& operator<<(std::ostream& out, const Rule& rule) { rule.print(out); return out; } }; std::vector Rule::defaultValues_; std::map Rule::defaultMapping_; void Rule::setDefault(const eckit::Value& values, const eckit::Value& ids) { std::map precedence; for (size_t i = 0; i < values.size(); ++i) { const eckit::Value& id = values[i]; std::string first = id; defaultValues_.push_back(first); const eckit::Value& aliases = ids[id]; if (aliases.isNil()) { LOG_DEBUG_LIB(LibMetkit) << "No aliases for " << id << std::endl; continue; } for (size_t j = 0; j < aliases.size(); ++j) { std::string v = aliases[j]; if (defaultMapping_.find(v) != defaultMapping_.end()) { if (precedence[v] <= j) { LOG_DEBUG_LIB(LibMetkit) << "Redefinition ignored: param " << v << "='" << first << "', keeping previous value of '" << defaultMapping_[v] << "' " << std::endl; continue; } else { LOG_DEBUG_LIB(LibMetkit) << "Redefinition of param " << v << "='" << first << "', overriding previous value of '" << defaultMapping_[v] << "' " << std::endl; precedence[v] = j; } } else { precedence[v] = j; } defaultMapping_[v] = first; defaultValues_.push_back(v); } } } Rule::Rule(const eckit::Value& matchers, const eckit::Value& values, const eckit::Value& ids) { std::map precedence; const eckit::Value& keys = matchers.keys(); for (size_t i = 0; i < keys.size(); ++i) { std::string name = keys[i]; matchers_.push_back(Matcher(name, matchers[name])); } for (size_t i = 0; i < values.size(); ++i) { const eckit::Value& id = values[i]; std::string first = id; values_.push_back(first); const eckit::Value& aliases = ids[id]; if (aliases.isNil()) { LOG_DEBUG_LIB(LibMetkit) << "No aliases for " << id << " " << *this << std::endl; continue; } for (size_t j = 0; j < aliases.size(); ++j) { std::string v = aliases[j]; if (mapping_.find(v) != mapping_.end()) { if (precedence[v] <= j) { LOG_DEBUG_LIB(LibMetkit) << "Redefinition ignored: param " << v << "='" << first << "', keeping previous value of '" << mapping_[v] << "' " << *this << std::endl; continue; } else { LOG_DEBUG_LIB(LibMetkit) << "Redefinition of param " << v << "='" << first << "', overriding previous value of '" << mapping_[v] << "' " << *this << std::endl; precedence[v] = j; } } else { precedence[v] = j; } mapping_[v] = {first}; values_.push_back(v); } } } bool Rule::match(const metkit::mars::MarsRequest& request, bool partial) const { for (std::vector::const_iterator j = matchers_.begin(); j != matchers_.end(); ++j) { if (!(*j).match(request, partial)) { return false; } } return true; } std::string Rule::lookup(const std::string& s, bool fail) const { size_t table = 0; size_t param = 0; size_t* n = ¶m; bool ok = true; for (std::string::const_iterator k = s.begin(); k != s.end(); ++k) { switch (*k) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': (*n) *= 10; (*n) += (*k) - '0'; break; case '.': if (n == ¶m) { n = &table; } else { ok = false; } break; default: ok = false; break; } } if (ok && param > 0) { std::ostringstream oss; if (table == 128) { table = 0; } if (table > 0 && param >= 1000) { throw eckit::UserError("Unrecognised format for parameter " + s, Here()); } oss << table * 1000 + param; std::string p = oss.str(); for (std::vector::const_iterator j = values_.begin(); j != values_.end(); ++j) { if ((*j) == p) { return p; } } for (std::vector::const_iterator j = defaultValues_.begin(); j != defaultValues_.end(); ++j) { if ((*j) == p) { return p; } } throw eckit::UserError("Cannot match parameter " + p, Here()); } std::string paramid = metkit::mars::MarsLanguage::bestMatch(s, values_, false, false, true, mapping_); if (!paramid.empty()) { return paramid; } return metkit::mars::MarsLanguage::bestMatch(s, defaultValues_, fail, false, false, defaultMapping_); } static std::vector* rules = nullptr; } // namespace static void init() { local_mutex = new eckit::Mutex(); rules = new std::vector(); const eckit::Value ids = eckit::YAMLParser::decodeFile(LibMetkit::paramIDYamlFile()); ASSERT(ids.isOrderedMap()); eckit::ValueMap merge; static bool metkitLegacyParamCheck = eckit::Resource("metkitLegacyParamCheck;$METKIT_LEGACY_PARAM_CHECK", false); static bool metkitRawParam = eckit::Resource("metkitRawParam;$METKIT_RAW_PARAM", false); if (metkitLegacyParamCheck || (!metkitRawParam)) { eckit::Value r = eckit::YAMLParser::decodeFile(LibMetkit::paramYamlFile()); ASSERT(r.isList()); const eckit::Value rs = eckit::YAMLParser::decodeFile(LibMetkit::paramStaticYamlFile()); ASSERT(rs.isList()); // merge r and rs for (size_t i = 0; i < r.size(); ++i) { const eckit::Value& rule = r[i]; if (!rule.isList()) { rule.dump(Log::error()) << std::endl; } ASSERT(rule.isList()); ASSERT(rule.size() == 2); merge.emplace(rule[0], rule[1]); } for (size_t i = 0; i < rs.size(); ++i) { const eckit::Value& rule = rs[i]; if (!rule.isList()) { rule.dump(Log::error()) << std::endl; } ASSERT(rule.isList()); ASSERT(rule.size() == 2); auto it = merge.find(rule[0]); if (it == merge.end()) { merge.emplace(rule[0], rule[1]); } else { it->second += rule[1]; } } } if (metkitLegacyParamCheck) { for (auto it = merge.begin(); it != merge.end(); it++) { (*rules).push_back(Rule(it->first, it->second, ids)); } return; } auto keys = ids.keys(); Rule::setDefault(keys, ids); if (metkitRawParam) { // empty rule, to enable default (*rules).push_back(Rule(eckit::Value::makeMap(), eckit::Value::makeList(), eckit::Value::makeMap())); return; } std::set shortnames; std::set associatedIDs; const eckit::Value pc = eckit::YAMLParser::decodeFile(LibMetkit::shortnameContextYamlFile()); ASSERT(pc.isList()); for (size_t i = 0; i < pc.size(); i++) { shortnames.emplace(pc[i]); } for (size_t i = 0; i < keys.size(); i++) { auto el = ids.element(keys[i]); for (size_t j = 0; j < el.size(); j++) { if (shortnames.find(el[j]) != shortnames.end()) { associatedIDs.emplace(keys[i]); } } } for (auto it = merge.begin(); it != merge.end(); it++) { auto listIDs = eckit::Value::makeList(); for (size_t j = 0; j < it->second.size(); j++) { if (associatedIDs.find(it->second[j]) != associatedIDs.end()) { listIDs.append(it->second[j]); } } if (listIDs.size() > 0) { (*rules).push_back(Rule{it->first, listIDs, ids}); } } (*rules).push_back(Rule{eckit::Value::makeMap(), eckit::Value::makeList(), eckit::Value::makeMap()}); } namespace metkit::mars { //---------------------------------------------------------------------------------------------------------------------- TypeParam::TypeParam(const std::string& name, const eckit::Value& settings) : Type(name, settings), firstRule_(false) { if (settings.contains("expand_with")) { expandWith_ = settings["expand_with"]; } if (settings.contains("first_rule")) { firstRule_ = settings["first_rule"]; } } void TypeParam::print(std::ostream& out) const { out << "TypeParam[name=" << name_ << "]"; } void TypeParam::pass2(MarsRequest& request) { pthread_once(&once, init); bool fail = true; const Rule* rule = 0; std::vector values = request.values(name_, true); if (values.size() == 1 && values[0] == "all") { return; } eckit::AutoLock lock(local_mutex); for (const auto& r : *rules) { if (r.match(request)) { rule = &r; break; } } if (!rule) { Log::warning() << "TypeParam: cannot find a context to expand 'param' in " << request << std::endl; if (firstRule_) { bool found = false; for (const auto& r : *rules) { if (r.match(request, true)) { for (std::vector::iterator j = values.begin(); j != values.end() && !rule; ++j) { std::string& s = (*j); try { s = r.lookup(s, fail); rule = &r; Log::warning() << "TypeParam: using 'first matching rule' option " << r << std::endl; } catch (...) { } } } } } else if (expandWith_.size()) { MarsRequest tmp(request); for (auto j = expandWith_.begin(); j != expandWith_.end(); ++j) { if (!tmp.has((*j).first)) { tmp.setValue((*j).first, (*j).second); } } for (const auto& r : *rules) { if (r.match(tmp)) { rule = &r; Log::warning() << "TypeParam using 'expand with' option " << *rule << std::endl; break; } } } if (!rule) { std::ostringstream oss; oss << "TypeParam: cannot find a context to expand 'param' in " << request; throw eckit::SeriousBug(oss.str()); } } for (std::vector::iterator j = values.begin(); j != values.end(); ++j) { std::string& s = (*j); try { s = rule->lookup(s, fail); } catch (...) { Log::error() << *rule << std::endl; throw; } } request.setValuesTyped(this, values); } bool TypeParam::expand(std::string&, const MarsRequest&) const { // Work done on pass2() return true; } void TypeParam::reset() { // cache_.clear(); Type::reset(); } static TypeBuilder type("param"); //---------------------------------------------------------------------------------------------------------------------- } // namespace metkit::mars metkit-1.16.0/src/metkit/mars/TypeParam.h000066400000000000000000000024211513171467200202030ustar00rootroot00000000000000/* * (C) Copyright 1996- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ /// @file TypeParam.h /// @author Baudouin Raoult /// @author Tiago Quintino /// @date April 2016 #pragma once #include "metkit/mars/Type.h" namespace metkit::mars { //---------------------------------------------------------------------------------------------------------------------- class TypeParam : public Type { public: // methods TypeParam(const std::string& name, const eckit::Value& settings); ~TypeParam() noexcept override = default; private: // methods eckit::ValueMap expandWith_; bool firstRule_; void print(std::ostream& out) const override; void reset() override; void pass2(MarsRequest& request) override; bool expand(std::string& value, const MarsRequest& request) const override; }; //---------------------------------------------------------------------------------------------------------------------- } // namespace metkit::mars metkit-1.16.0/src/metkit/mars/TypeRange.cc000066400000000000000000000035551513171467200203460ustar00rootroot00000000000000/* * (C) Copyright 1996- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ #include #include "metkit/mars/TypeRange.h" #include "eckit/exception/Exceptions.h" #include "eckit/utils/StringTools.h" #include "eckit/utils/Tokenizer.h" #include "metkit/config/LibMetkit.h" #include "metkit/mars/MarsLanguage.h" #include "metkit/mars/Quantile.h" #include "metkit/mars/StepRange.h" #include "metkit/mars/TypeTime.h" #include "metkit/mars/TypeToByList.h" #include "metkit/mars/TypesFactory.h" namespace metkit::mars { //---------------------------------------------------------------------------------------------------------------------- class ExtendedTime : public eckit::Time { public: ExtendedTime(long seconds = 0) : Time(seconds, true) {} ExtendedTime(const std::string& time) : Time(time, true) {} }; //---------------------------------------------------------------------------------------------------------------------- TypeRange::TypeRange(const std::string& name, const eckit::Value& settings) : Type(name, settings) { toByList_ = std::make_unique>(*this, settings); multiple_ = true; } void TypeRange::print(std::ostream& out) const { out << "TypeRange[name=" << name_ << "]"; } bool TypeRange::expand(std::string& value, const MarsRequest&) const { value = StepRange{value}; return true; } static TypeBuilder type("range"); //---------------------------------------------------------------------------------------------------------------------- } // namespace metkit::mars metkit-1.16.0/src/metkit/mars/TypeRange.h000066400000000000000000000022141513171467200201770ustar00rootroot00000000000000/* * (C) Copyright 1996- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ /// @file TypeRange.h /// @author Emanuele Danovaro /// @date February 2022 #pragma once #include "metkit/mars/Type.h" namespace metkit::mars { class StepRange; //---------------------------------------------------------------------------------------------------------------------- class TypeRange : public Type { public: // methods TypeRange(const std::string& name, const eckit::Value& settings); ~TypeRange() noexcept override = default; private: // methods void print(std::ostream& out) const override; bool expand(std::string& value, const MarsRequest& request) const override; }; //---------------------------------------------------------------------------------------------------------------------- } // namespace metkit::mars metkit-1.16.0/src/metkit/mars/TypeRegex.cc000066400000000000000000000035171513171467200203620ustar00rootroot00000000000000/* * (C) Copyright 1996- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ #include "metkit/mars/TypeRegex.h" #include "eckit/parser/JSONParser.h" #include "eckit/utils/StringTools.h" #include "metkit/mars/MarsLanguage.h" #include "metkit/mars/TypesFactory.h" namespace metkit { namespace mars { //---------------------------------------------------------------------------------------------------------------------- TypeRegex::TypeRegex(const std::string& name, const eckit::Value& settings) : Type(name, settings), uppercase_(false) { if (settings.contains("uppercase")) { uppercase_ = settings["uppercase"]; } eckit::Value r = settings["regex"]; if (r.isList()) { for (size_t i = 0; i < r.size(); ++i) { regex_.push_back(std::string(r[i])); } } else { regex_.push_back(std::string(r)); } } bool TypeRegex::expand(std::string& value, const MarsRequest&) const { for (std::vector::const_iterator j = regex_.begin(); j != regex_.end(); ++j) { if ((*j).match(value)) { if (uppercase_) { value = eckit::StringTools::upper(value); } return true; } } return false; } void TypeRegex::print(std::ostream& out) const { out << "TypeRegex[name=" << name_ << "]"; } static TypeBuilder type("regex"); //---------------------------------------------------------------------------------------------------------------------- } // namespace mars } // namespace metkit metkit-1.16.0/src/metkit/mars/TypeRegex.h000066400000000000000000000024661513171467200202260ustar00rootroot00000000000000/* * (C) Copyright 1996- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ /// @file TypeRegex.h /// @author Baudouin Raoult /// @author Tiago Quintino /// @date April 2016 #ifndef metkit_TypeRegex_H #define metkit_TypeRegex_H #include "eckit/utils/Regex.h" #include "metkit/mars/Type.h" namespace metkit { namespace mars { //---------------------------------------------------------------------------------------------------------------------- class TypeRegex : public Type { public: // methods TypeRegex(const std::string& name, const eckit::Value& settings); ~TypeRegex() noexcept override = default; private: // methods void print(std::ostream& out) const override; bool expand(std::string& value, const MarsRequest& request) const override; std::vector regex_; bool uppercase_; }; //---------------------------------------------------------------------------------------------------------------------- } // namespace mars } // namespace metkit #endif metkit-1.16.0/src/metkit/mars/TypeTime.cc000066400000000000000000000034721513171467200202060ustar00rootroot00000000000000/* * (C) Copyright 1996- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ #include #include #include "metkit/mars/TypeTime.h" #include "metkit/mars/TypeToByList.h" #include "metkit/mars/TypesFactory.h" namespace metkit::mars { //---------------------------------------------------------------------------------------------------------------------- TypeTime::TypeTime(const std::string& name, const eckit::Value& settings) : Type(name, settings) { toByList_ = std::make_unique>(*this, settings); multiple_ = true; } bool TypeTime::expand(std::string& value, const MarsRequest&) const { eckit::Time time(value); std::ostringstream oss; if (time.seconds() != 0) { oss << "Cannot normalise time '" << value << "' - seconds not supported"; throw eckit::BadValue(oss.str(), Here()); } if (time.hours() >= 24) { oss << "Cannot normalise time '" << value << "' - " << time.hours() << " hours > 24 not supported"; throw eckit::BadValue(oss.str(), Here()); } oss << std::setfill('0') << std::setw(2) << time.hours() << std::setfill('0') << std::setw(2) << time.minutes(); value = oss.str(); return true; } void TypeTime::print(std::ostream& out) const { out << "TypeTime[name=" << name_ << "]"; } static TypeBuilder type("time"); //---------------------------------------------------------------------------------------------------------------------- } // namespace metkit::mars metkit-1.16.0/src/metkit/mars/TypeTime.h000066400000000000000000000023311513171467200200410ustar00rootroot00000000000000/* * (C) Copyright 1996- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ /// @file TypeTime.h /// @author Baudouin Raoult /// @author Tiago Quintino /// @author Emanuele Danovaro /// @date April 2016 #ifndef metkit_TypeTime_H #define metkit_TypeTime_H #include "metkit/mars/Type.h" namespace metkit::mars { //---------------------------------------------------------------------------------------------------------------------- class TypeTime : public Type { public: // methods TypeTime(const std::string& name, const eckit::Value& settings); ~TypeTime() noexcept override = default; private: // methods void print(std::ostream& out) const override; bool expand(std::string& value, const MarsRequest& request) const override; }; //---------------------------------------------------------------------------------------------------------------------- } // namespace metkit::mars #endif metkit-1.16.0/src/metkit/mars/TypeToByList.h000066400000000000000000000112431513171467200206560ustar00rootroot00000000000000/* * (C) Copyright 1996- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ /// @file TypeToByList.h /// @author Emanuele Danovaro /// @date March 2025 #pragma once #include "eckit/exception/Exceptions.h" #include "eckit/utils/StringTools.h" #include "eckit/utils/Translator.h" #include "metkit/mars/Type.h" namespace metkit::mars { //---------------------------------------------------------------------------------------------------------------------- template class TypeToByList : public ITypeToByList { private: // members const Type& type_; const std::string by_; public: // methods TypeToByList(const Type& type, const eckit::Value& settings) : type_(type), by_(settings.contains("by") ? settings["by"] : "1") {} virtual ~TypeToByList() = default; void expandRanges(std::vector& values, const MarsRequest& request) const override { if (values.size() == 1) { return; } static eckit::Translator s2el; static eckit::Translator s2by; static eckit::Translator el2s; std::vector newval; for (size_t i = 0; i < values.size(); ++i) { const std::string& s = values[i]; if (eckit::StringTools::lower(s) == "to" || eckit::StringTools::lower(s) == "t0") { // TimeUnit unit; if (newval.size() == 0) { std::ostringstream oss; oss << type_.name() << " list: 'to' must be preceeded by a starting value."; throw eckit::BadValue(oss.str()); } if (values.size() <= i + 1) { std::ostringstream oss; oss << type_.name() << " list: 'to' must be followed by an ending value."; throw eckit::BadValue(oss.str()); } EL from = s2el(type_.tidy(values[i - 1], request)); std::string to_s = type_.tidy(values[i + 1], request); EL to = s2el(to_s); BY by = s2by(by_); if (i + 2 < values.size() && eckit::StringTools::lower(values[i + 2]) == "by") { if (values.size() <= i + 3) { std::ostringstream oss; oss << type_.name() << " list: 'by' must be followed by a step size."; throw eckit::BadValue(oss.str()); } by = s2by(values[i + 3]); i += 2; } i++; if (by == BY{0}) { std::ostringstream oss; oss << type_.name() + ": 'by' value " << by << " cannot be zero"; throw eckit::BadValue(oss.str()); } if (from < to && by < BY{0}) { std::ostringstream oss; oss << type_.name() << ": impossible to define a sequence starting from " << from << " to " << to << " with step " << by; throw eckit::BadValue(oss.str()); } bool addBy = (from < to && by > BY{0}) || (from > to && by < BY{0}); if (from == to) { continue; } EL j = from; while (j != to) { std::string j_s; try { if (addBy) { j += by; } else { j -= by; } j_s = type_.tidy(el2s(j), request); } catch (...) { break; /// reached an invalid value } if (((from < to && j > to) || (from > to && j < to)) && j != to && j_s != to_s) { break; } newval.push_back(j_s); } } else { newval.push_back(type_.tidy(s, request)); } } std::swap(values, newval); } }; //---------------------------------------------------------------------------------------------------------------------- } // namespace metkit::mars metkit-1.16.0/src/metkit/mars/TypeToByListQuantile.cc000066400000000000000000000050301513171467200225140ustar00rootroot00000000000000/* * (C) Copyright 1996- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ #include #include "metkit/mars/TypeToByListQuantile.h" #include "eckit/exception/Exceptions.h" #include "eckit/utils/StringTools.h" #include "eckit/utils/Tokenizer.h" #include "metkit/config/LibMetkit.h" #include "metkit/mars/MarsLanguage.h" #include "metkit/mars/Quantile.h" #include "metkit/mars/TypeToByList.h" #include "metkit/mars/TypesFactory.h" namespace metkit::mars { //---------------------------------------------------------------------------------------------------------------------- TypeToByListQuantile::TypeToByListQuantile(const std::string& name, const eckit::Value& settings) : Type(name, settings) { eckit::Value values = settings["denominators"]; if (!values.isList()) { values = MarsLanguage::jsonFile(values); ASSERT(values.isList()); } for (size_t i = 0; i < values.size(); ++i) { const eckit::Value& val = values[i]; if (val.isNumber()) { long v = val; if (denominators_.find(v) == denominators_.end()) { denominators_.emplace(v); } else { std::ostringstream oss; oss << "Redefined " << v << "-quantile"; throw eckit::SeriousBug(oss.str()); } } } LOG_DEBUG_LIB(LibMetkit) << "TypeToByListQuantile name=" << name << " denominators " << denominators_ << std::endl; toByList_ = std::make_unique>(*this, settings); multiple_ = true; } void TypeToByListQuantile::print(std::ostream& out) const { out << "TypeToByListQuantile[name=" << name_ << "]"; } bool TypeToByListQuantile::expand(std::string& value, const MarsRequest&) const { Quantile q(value); if (denominators_.find(q.den()) == denominators_.end()) { std::ostringstream oss; oss << name_ << ": " << q.den() << "-quantile not supported."; throw eckit::BadValue(oss.str()); } return true; } static TypeBuilder type("to-by-list-quantile"); //---------------------------------------------------------------------------------------------------------------------- } // namespace metkit::mars metkit-1.16.0/src/metkit/mars/TypeToByListQuantile.h000066400000000000000000000023521513171467200223620ustar00rootroot00000000000000/* * (C) Copyright 1996- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ /// @file TypeToByListQuantile.h /// @author Emanuele Danovaro /// @date February 2022 #pragma once #include "metkit/mars/Quantile.h" #include "metkit/mars/Type.h" namespace metkit::mars { //---------------------------------------------------------------------------------------------------------------------- class TypeToByListQuantile : public Type { public: // methods TypeToByListQuantile(const std::string& name, const eckit::Value& settings); ~TypeToByListQuantile() noexcept override = default; private: // methods void print(std::ostream& out) const override; bool expand(std::string& value, const MarsRequest& request) const override; std::set denominators_; }; //---------------------------------------------------------------------------------------------------------------------- } // namespace metkit::mars metkit-1.16.0/src/metkit/mars/TypesFactory.cc000066400000000000000000000055161513171467200211030ustar00rootroot00000000000000/* * (C) Copyright 1996- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ #include "eckit/exception/Exceptions.h" #include "eckit/thread/AutoLock.h" #include "eckit/value/Value.h" #include "metkit/mars/TypesFactory.h" namespace metkit { namespace mars { //---------------------------------------------------------------------------------------------------------------------- TypesFactory::TypesFactory(const std::string& name) : name_(name) { TypesRegistry::instance().add(name, this); } TypesFactory::~TypesFactory() { TypesRegistry::instance().remove(name_); } Type* TypesRegistry::build(const std::string& keyword, const eckit::Value& settings) { std::string name; if (settings["type"].isList()) { name = "mixed"; } else { name = std::string(settings["type"]); } eckit::AutoLock lock(mutex_); std::map::const_iterator j = m_.find(name); if (j == m_.end()) { eckit::Log::error() << "No TypesFactory for [" << name << "]" << std::endl; eckit::Log::error() << "KeywordTypes are:" << std::endl; for (j = m_.begin(); j != m_.end(); ++j) eckit::Log::error() << " " << (*j).first << std::endl; throw eckit::SeriousBug(std::string("No TypesFactory called ") + name); } return (*j).second->make(keyword, settings); } void TypesRegistry::list(std::ostream& s) { eckit::AutoLock lock(mutex_); s << "["; bool first = true; std::map::const_iterator j = m_.begin(); while (j != m_.end()) { if (!first) s << ","; s << (j++)->first; first = false; } s << "]"; } Type* TypesFactory::build(const std::string& keyword, const eckit::Value& settings) { return TypesRegistry::instance().build(keyword, settings); } void TypesFactory::list(std::ostream& s) { TypesRegistry::instance().list(s); } TypesRegistry& TypesRegistry::instance() { static TypesRegistry instance; return instance; } void TypesRegistry::add(const std::string& name, TypesFactory* f) { eckit::AutoLock lock(mutex_); ASSERT(m_.find(name) == m_.end()); m_[name] = f; } void TypesRegistry::remove(const std::string& name) { eckit::AutoLock lock(mutex_); m_.erase(name); } //---------------------------------------------------------------------------------------------------------------------- } // namespace mars } // namespace metkit metkit-1.16.0/src/metkit/mars/TypesFactory.h000066400000000000000000000043131513171467200207370ustar00rootroot00000000000000/* * (C) Copyright 1996- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ /// @file TypesFactory.h /// @author Baudouin Raoult /// @author Tiago Quintino /// @date April 2016 #ifndef metkit_TypesFactory_H #define metkit_TypesFactory_H #include #include "eckit/memory/NonCopyable.h" #include "eckit/types/Types.h" namespace eckit { class Value; } namespace metkit { namespace mars { class Type; class TypesFactory; //---------------------------------------------------------------------------------------------------------------------- class TypesRegistry : private eckit::NonCopyable { eckit::Mutex mutex_; std::map m_; public: static TypesRegistry& instance(); void add(const std::string& name, TypesFactory* f); void remove(const std::string& name); Type* build(const std::string& keyword, const eckit::Value&); void list(std::ostream& s); }; /// A self-registering factory for producing TypesFactory instances class TypesFactory { public: virtual Type* make(const std::string& keyword, const eckit::Value& settings) const = 0; static Type* build(const std::string& keyword, const eckit::Value& settings); static void list(std::ostream& s); protected: TypesFactory(const std::string&); ~TypesFactory(); std::string name_; }; /// Templated specialisation of the self-registering factory, /// that does the self-registration, and the construction of each object. template class TypeBuilder : public TypesFactory { Type* make(const std::string& keyword, const eckit::Value& settings) const override { return new T(keyword, settings); } public: TypeBuilder(const std::string& name) : TypesFactory(name) {} }; //---------------------------------------------------------------------------------------------------------------------- } // namespace mars } // namespace metkit #endif metkit-1.16.0/src/metkit/metkit_config.h.in000066400000000000000000000013301513171467200205640ustar00rootroot00000000000000/* * (C) Copyright 1996- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation * nor does it submit to any jurisdiction. */ #ifndef metkit_config_h #define metkit_config_h #include "metkit_ecbuild_config.h" /* generated by ecbuild */ /* variables */ #cmakedefine metkit_HAVE_GRIB #cmakedefine metkit_HAVE_NETCDF #cmakedefine metkit_HAVE_BUFR #cmakedefine metkit_HAVE_ODB #cmakedefine metkit_HAVE_FAIL_ON_CCSDS /* packages */ #endif /* metkit_config_h */ metkit-1.16.0/src/metkit/metkit_version.c000066400000000000000000000006521513171467200204000ustar00rootroot00000000000000#include "metkit_version.h" #ifdef __cplusplus extern "C" { #endif const char* metkit_version() { return metkit_VERSION; } unsigned int metkit_version_int() { return 10000 * metkit_VERSION_MAJOR + 100 * metkit_VERSION_MINOR + 1 * metkit_VERSION_PATCH; } const char* metkit_version_str() { return metkit_VERSION_STR; } const char* metkit_git_sha1() { return metkit_GIT_SHA1; } #ifdef __cplusplus } #endif metkit-1.16.0/src/metkit/metkit_version.h.in000066400000000000000000000011101513171467200210000ustar00rootroot00000000000000#ifndef metkit_version_h #define metkit_version_h #define metkit_VERSION_STR "@metkit_VERSION_STR@" #define metkit_VERSION "@metkit_VERSION@" #define metkit_VERSION_MAJOR @metkit_VERSION_MAJOR@ #define metkit_VERSION_MINOR @metkit_VERSION_MINOR@ #define metkit_VERSION_PATCH @metkit_VERSION_PATCH@ #define metkit_GIT_SHA1 "@metkit_GIT_SHA1@" #ifdef __cplusplus extern "C" { #endif const char * metkit_version(); unsigned int metkit_version_int(); const char * metkit_version_str(); const char * metkit_git_sha1(); #ifdef __cplusplus } #endif #endif // metkit_version_h metkit-1.16.0/src/metkit/odb/000077500000000000000000000000001513171467200157335ustar00rootroot00000000000000metkit-1.16.0/src/metkit/odb/IdMapper.cc000066400000000000000000000070511513171467200177460ustar00rootroot00000000000000/* * (C) Copyright 1996-2012 ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ #include "metkit/odb/IdMapper.h" #include #include #include #include "eckit/config/Resource.h" #include "eckit/filesystem/PathName.h" #include "eckit/log/Log.h" #include "eckit/utils/StringTools.h" #include "metkit/config/LibMetkit.h" using namespace eckit; namespace metkit { namespace odb { //---------------------------------------------------------------------------------------------------------------------- IdMapper::IdMapper() : maps_{{"CLASS", IdMap{"class.table"}}, {"TYPE", IdMap{"type.table"}}, {"STREAM", IdMap{"stream.table"}}, {"OBSGROUP", IdMap{"group.txt", ";", 0, 3}}} {} IdMapper::~IdMapper() {} IdMapper& IdMapper::instance() { static IdMapper themapper; return themapper; } //---------------------------------------------------------------------------------------------------------------------- bool IdMapper::alphanumeric(const std::string& keyword, long numeric, std::string& output) { auto idmap = maps_.find(StringTools::upper(keyword)); if (idmap == maps_.end()) { return false; } output = idmap->second.alphanumeric(numeric); return true; } bool IdMapper::alphanumeric(const std::string& keyword, const std::set& numeric, std::set& output) { auto idmap = maps_.find(StringTools::upper(keyword)); if (idmap == maps_.end()) { return false; } output.clear(); std::transform(numeric.begin(), numeric.end(), std::inserter(output, output.begin()), [&idmap](long l) { return idmap->second.alphanumeric(l); }); return true; } static PathName& codes_path() { static PathName p = Resource("$ODB_CODES", "~metkit/share/metkit/odb"); return p; } IdMap::IdMap(const std::string& configFile, const std::string& fieldDelimiter, size_t numericIndex, size_t alphanumericIndex) { PathName configPath = codes_path() / configFile; LOG_DEBUG_LIB(LibMetkit) << "GribCodesBase::GribCodesBase: config file:" << configPath << std::endl; numeric2alpha_.clear(); std::ifstream fin(configPath.asString()); std::string line; while (std::getline(fin, line)) { std::vector words = StringTools::split(fieldDelimiter, line); if (words.size() >= 2) { long num = eckit::Translator()(StringTools::trim(words[numericIndex])); std::string alpha(StringTools::trim(words[alphanumericIndex])); numeric2alpha_[num] = StringTools::lower(alpha); LOG_DEBUG_LIB(LibMetkit) << "GribCodesBase::readConfig: num='" << num << "' alpha='" << alpha << "'" << std::endl; } } } IdMap::~IdMap() {} std::string IdMap::alphanumeric(long numeric) { auto it = numeric2alpha_.find(numeric); if (it == numeric2alpha_.end()) { std::stringstream ss; ss << "Numeric code " << numeric << " not found"; throw UserError(ss.str(), Here()); } return it->second; } //---------------------------------------------------------------------------------------------------------------------- } // namespace odb } // namespace metkit metkit-1.16.0/src/metkit/odb/IdMapper.h000066400000000000000000000035031513171467200176060ustar00rootroot00000000000000/* * (C) Copyright 1996-2012 ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ /// @author Piotr Kuchta /// @date April 2011 /// @author Simon Smart /// @date April 2019 #ifndef metkit_odb_IdMapper_H #define metkit_odb_IdMapper_H #include #include #include #include namespace eckit { class PathName; } namespace metkit { namespace odb { //---------------------------------------------------------------------------------------------------------------------- class IdMap { public: // methods IdMap(const std::string& configFile, const std::string& fieldDelimiter = " \t", size_t numericIndex = 0, size_t alphanumericIndex = 1); ~IdMap(); std::string alphanumeric(long numeric); private: // methods std::map numeric2alpha_; }; //---------------------------------------------------------------------------------------------------------------------- class IdMapper { public: // methods static IdMapper& instance(); /// Returns true if modified bool alphanumeric(const std::string& keyword, long numeric, std::string& output); bool alphanumeric(const std::string& keyword, const std::set& numeric, std::set& output); private: // methods IdMapper(); ~IdMapper(); private: // members std::map maps_; }; //---------------------------------------------------------------------------------------------------------------------- } // namespace odb } // namespace metkit #endif metkit-1.16.0/src/metkit/odb/OdbContent.cc000066400000000000000000000025351513171467200203060ustar00rootroot00000000000000/* * (C) Copyright 2017- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ /// @author Baudouin Raoult /// @date Jun 2020 #include "metkit/odb/OdbContent.h" #include "eckit/exception/Exceptions.h" #include "eckit/io/DataHandle.h" #include "eckit/io/MemoryHandle.h" namespace metkit { namespace codes { OdbContent::OdbContent(eckit::Buffer&& buffer) : frame_(std::move(buffer)) {} OdbContent::OdbContent(eckit::DataHandle& handle, size_t size) : frame_(size) { ASSERT(handle.read(frame_, frame_.size()) == frame_.size()); } OdbContent::~OdbContent() {} const void* OdbContent::data() const { return frame_; } size_t OdbContent::length() const { return frame_.size(); } eckit::DataHandle* OdbContent::readHandle() const { return new eckit::MemoryHandle(frame_, frame_.size()); } void OdbContent::write(eckit::DataHandle& handle) const { ASSERT(handle.write(frame_, frame_.size()) == frame_.size()); } void OdbContent::print(std::ostream& s) const { s << "OdbContent[]"; } } // namespace codes } // namespace metkit metkit-1.16.0/src/metkit/odb/OdbContent.h000066400000000000000000000022041513171467200201410ustar00rootroot00000000000000/* * (C) Copyright 2017- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ /// @author Baudouin Raoult /// @date Jun 2020 #ifndef metkit_codes_OdbContent_H #define metkit_codes_OdbContent_H #include "eckit/io/Buffer.h" #include "eckit/message/MessageContent.h" namespace metkit { namespace codes { class OdbContent : public eckit::message::MessageContent { public: OdbContent(eckit::Buffer&&); OdbContent(eckit::DataHandle&, size_t size); ~OdbContent(); private: eckit::Buffer frame_; virtual size_t length() const override; const void* data() const override; virtual eckit::DataHandle* readHandle() const override; virtual void write(eckit::DataHandle& handle) const override; virtual void print(std::ostream& s) const override; }; } // namespace codes } // namespace metkit #endif metkit-1.16.0/src/metkit/odb/OdbDecoder.cc000066400000000000000000000043661513171467200202450ustar00rootroot00000000000000/* * (C) Copyright 1996- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ #include "metkit/odb/OdbDecoder.h" #include #include "eckit/config/Resource.h" #include "eckit/config/YAMLConfiguration.h" #include "eckit/io/DataHandle.h" #include "eckit/message/Message.h" #include "eckit/serialisation/MemoryStream.h" #include "eckit/types/Types.h" #include "eckit/utils/StringTools.h" #include "metkit/mars/MarsRequest.h" #include "metkit/odb/OdbMetadataDecoder.h" namespace metkit { namespace codes { //---------------------------------------------------------------------------------------------------------------------- bool OdbDecoder::match(const eckit::message::Message& msg) const { size_t len = msg.length(); const unsigned char* p = static_cast(msg.data()); return len >= 5 and ((p[0] == 0xff and p[1] == 0xff and p[2] == 'O' and p[3] == 'D' and p[4] == 'A')); } void OdbDecoder::getMetadata(const eckit::message::Message& msg, eckit::message::MetadataGatherer& gather, const eckit::message::GetMetadataOptions& options) const { std::unique_ptr handle(msg.readHandle()); handle->openForRead(); eckit::AutoClose close(*handle); odc::api::Reader reader(*handle, false); odc::api::Frame frame; OdbMetadataDecoder setter(gather, options); while ((frame = reader.next())) { odc::api::Span span = frame.span(OdbMetadataDecoder::columnNames(), true); span.visit(setter); } } eckit::Buffer OdbDecoder::decode(const eckit::message::Message& msg) const { NOTIMP; // Not relevant for MultIO hackathon. Implement as needed in future. } void OdbDecoder::print(std::ostream& s) const { s << "OdbDecoder[]"; } static OdbDecoder decoder; //---------------------------------------------------------------------------------------------------------------------- } // namespace codes } // namespace metkit metkit-1.16.0/src/metkit/odb/OdbDecoder.h000066400000000000000000000023631513171467200201020ustar00rootroot00000000000000/* * (C) Copyright 1996- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ /// @author Baudouin Raoult /// @date Jun 2020 #pragma once #include "eckit/message/Decoder.h" namespace metkit { namespace codes { //---------------------------------------------------------------------------------------------------------------------- class OdbDecoder : public eckit::message::MessageDecoder { private: // methods bool match(const eckit::message::Message&) const override; void print(std::ostream&) const override; void getMetadata(const eckit::message::Message& msg, eckit::message::MetadataGatherer&, const eckit::message::GetMetadataOptions&) const override; eckit::Buffer decode(const eckit::message::Message& msg) const override; }; //---------------------------------------------------------------------------------------------------------------------- } // namespace codes } // namespace metkit metkit-1.16.0/src/metkit/odb/OdbMetadataDecoder.cc000066400000000000000000000104701513171467200216770ustar00rootroot00000000000000/* * (C) Copyright 1996- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ #include "metkit/odb/OdbMetadataDecoder.h" #include #include #include #include "eckit/config/Resource.h" #include "eckit/config/YAMLConfiguration.h" #include "eckit/utils/StringTools.h" #include "metkit/config/LibMetkit.h" #include "metkit/mars/MarsRequest.h" #include "metkit/mars/Type.h" #include "metkit/odb/IdMapper.h" namespace { class OdbColumnNameMapping { public: static OdbColumnNameMapping& instance() { static OdbColumnNameMapping mapping; return mapping; } const std::vector& columnNames() { return columnNames_; } const std::map& table() { return mapping_; } private: // methods OdbColumnNameMapping() { static eckit::PathName configPath( eckit::Resource("odbMarsRequestMapping", "~metkit/share/metkit/odb/marsrequest.yaml")); eckit::YAMLConfiguration config(configPath); for (const auto& key : config.keys()) { mapping_[config.getString(key)] = eckit::StringTools::lower(key); } columnNames_.reserve(mapping_.size()); for (const auto& kv : mapping_) { columnNames_.push_back(kv.first); } } private: // members std::map mapping_; std::vector columnNames_; }; } // namespace //---------------------------------------------------------------------------------------------------------------------- namespace metkit::codes { //---------------------------------------------------------------------------------------------------------------------- const std::vector& OdbMetadataDecoder::columnNames() { return OdbColumnNameMapping::instance().columnNames(); } template void OdbMetadataDecoder::visit(const std::string& columnName, const std::set& vals, const metkit::mars::MarsLanguage& language) { auto mapitr = OdbColumnNameMapping::instance().table().find(columnName); ASSERT(mapitr != OdbColumnNameMapping::instance().table().end()); std::string keyword = eckit::StringTools::lower(mapitr->second); metkit::mars::Type* t = language.type(keyword); ASSERT(options_.valueRepresentation == eckit::message::ValueRepresentation::String); for (auto val : vals) { std::string stringVal = eckit::Translator()(val); std::string tidyVal = t->tidy(stringVal); if (stringVal == tidyVal) // if t->tidy had no effect, set the original value gather_.setValue(keyword, val); else gather_.setValue(keyword, tidyVal); } } OdbMetadataDecoder::OdbMetadataDecoder(eckit::message::MetadataGatherer& gather, const eckit::message::GetMetadataOptions& options, const std::string& verb) : language_(verb), gather_(gather), options_(options) {} void OdbMetadataDecoder::operator()(const std::string& columnName, const std::set& vals) { LOG_DEBUG_LIB(LibMetkit) << "OdbMetadataDecoder::operator() columnName: " << columnName << " vals: " << vals << std::endl; auto mapitr = OdbColumnNameMapping::instance().table().find(columnName); ASSERT(mapitr != OdbColumnNameMapping::instance().table().end()); std::set mapped; if (metkit::odb::IdMapper::instance().alphanumeric(mapitr->second, vals, mapped)) { visit(columnName, mapped, language_); } else { visit(columnName, vals, language_); } } void OdbMetadataDecoder::operator()(const std::string& columnName, const std::set& vals) { visit(columnName, vals, language_); } void OdbMetadataDecoder::operator()(const std::string& columnName, const std::set& vals) { visit(columnName, vals, language_); } //---------------------------------------------------------------------------------------------------------------------- } // namespace metkit::codes metkit-1.16.0/src/metkit/odb/OdbMetadataDecoder.h000066400000000000000000000037041513171467200215430ustar00rootroot00000000000000/* * (C) Copyright 1996- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ /// @author Baudouin Raoult /// @date Jun 2020 #ifndef metkit_OdbMetadataDecoder_h #define metkit_OdbMetadataDecoder_h #include "eckit/message/Message.h" #include "metkit/mars/MarsLanguage.h" #include "odc/api/Odb.h" namespace metkit { namespace codes { //---------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------- class OdbMetadataDecoder : public odc::api::SpanVisitor { public: OdbMetadataDecoder(eckit::message::MetadataGatherer& gatherer, const eckit::message::GetMetadataOptions& options, const std::string& verb = "retrieve"); virtual void operator()(const std::string& columnName, const std::set& vals); virtual void operator()(const std::string& columnName, const std::set& vals); virtual void operator()(const std::string& columnName, const std::set& vals); static const std::vector& columnNames(); private: // methods template void visit(const std::string& columnName, const std::set& vals, const metkit::mars::MarsLanguage& language); private: // members metkit::mars::MarsLanguage language_; eckit::message::MetadataGatherer& gather_; eckit::message::GetMetadataOptions options_; }; //---------------------------------------------------------------------------------------------------------------------- } // namespace codes } // namespace metkit #endif metkit-1.16.0/src/metkit/odb/OdbSplitter.cc000066400000000000000000000063301513171467200204770ustar00rootroot00000000000000/* * (C) Copyright 1996- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ #include "metkit/odb/OdbSplitter.h" #include "eckit/io/BufferList.h" #include "eckit/io/PeekHandle.h" #include "eckit/message/Message.h" #include "metkit/config/LibMetkit.h" #include "metkit/odb/OdbContent.h" #include "metkit/odb/OdbMetadataDecoder.h" namespace metkit { namespace codes { OdbSplitter::OdbSplitter(eckit::PeekHandle& handle) : Splitter(handle), handleWrapper_(handle), reader_(handleWrapper_, false) {} OdbSplitter::~OdbSplitter() {} eckit::message::Message OdbSplitter::next() { if (!lastFrame_) { lastFrame_ = reader_.next(); if (!lastFrame_) { return eckit::message::Message(); } } eckit::BufferList buffers; odc::api::Span reference = lastFrame_.span(OdbMetadataDecoder::columnNames(), true); buffers.append(lastFrame_.encodedData()); handleWrapper_.clear(); LOG_DEBUG_LIB(LibMetkit) << "ODB frame: " << buffers.count() << ", size: " << lastFrame_.length() << ", total:" << buffers.size() << std::endl; lastFrame_ = odc::api::Frame(); //< we have consumed lastFrame_ odc::api::Frame frame; // aggregate all frames with the same metadata Span as reference Span while ((frame = reader_.next())) { odc::api::Span span = frame.span(OdbMetadataDecoder::columnNames(), true); if (span == reference) { buffers.append(frame.encodedData()); handleWrapper_.clear(); LOG_DEBUG_LIB(LibMetkit) << "ODB frame: " << buffers.count() << ", size: " << frame.length() << ", total:" << buffers.size() << std::endl; } else { // remember last frame to reuse as reference on the following next() lastFrame_ = frame; break; } } LOG_DEBUG_LIB(LibMetkit) << "Consolidating buffers of " << buffers.count() << " frames" << ", total size: " << buffers.size() << std::endl; return eckit::message::Message{new OdbContent(buffers.consolidate())}; } void OdbSplitter::print(std::ostream& s) const { s << "OdbSplitter[]"; } } // namespace codes } // namespace metkit //---------------------------------------------------------------------------------------------------------------------- namespace eckit { namespace message { template <> bool SplitterBuilder::match(eckit::PeekHandle& handle) const { unsigned char c0 = handle.peek(0); unsigned char c1 = handle.peek(1); unsigned char c2 = handle.peek(2); unsigned char c3 = handle.peek(3); unsigned char c4 = handle.peek(4); if (c0 == 0xff and c1 == 0xff and c2 == 'O' and c3 == 'D' and c4 == 'A') { return true; } return false; } } // namespace message } // namespace eckit static eckit::message::SplitterBuilder splitter; metkit-1.16.0/src/metkit/odb/OdbSplitter.h000066400000000000000000000025411513171467200203410ustar00rootroot00000000000000/* * (C) Copyright 1996- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ /// @author Baudouin Raoult /// @date Jun 2020 #ifndef metkit_OdbSplitter_h #define metkit_OdbSplitter_h #include "eckit/io/SeekableHandle.h" #include "eckit/message/Splitter.h" #include "odc/api/Odb.h" namespace eckit { class PeekHandle; } namespace metkit { namespace codes { //---------------------------------------------------------------------------------------------------------------------- class OdbSplitter : public eckit::message::Splitter { public: explicit OdbSplitter(eckit::PeekHandle&); ~OdbSplitter() override; private: // members eckit::SeekableHandle handleWrapper_; odc::api::Reader reader_; odc::api::Frame lastFrame_; private: // methods virtual eckit::message::Message next() override; virtual void print(std::ostream&) const override; }; //---------------------------------------------------------------------------------------------------------------------- } // namespace codes } // namespace metkit #endif metkit-1.16.0/src/metkit/odb/OdbToRequest.cc000066400000000000000000000052011513171467200206200ustar00rootroot00000000000000/* * (C) Copyright 1996-2012 ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ #include "metkit/odb/OdbToRequest.h" #include #include "eckit/io/DataHandle.h" #include "eckit/message/Message.h" #include "odc/api/Odb.h" #include "metkit/config/LibMetkit.h" #include "metkit/odb/OdbMetadataDecoder.h" using namespace eckit; using namespace odc::api; namespace metkit { using namespace mars; using namespace codes; namespace odb { //---------------------------------------------------------------------------------------------------------------------- class MarsRequestSetter : public eckit::message::MetadataGatherer { public: // methods MarsRequestSetter(MarsRequest& request) : request_(request) {} void setValue(const std::string& key, const std::string& value) override { request_.setValue(key, value); } void setValue(const std::string& key, long value) override { request_.setValue(key, value); } void setValue(const std::string& key, double value) override { request_.setValue(key, value); } private: // members MarsRequest& request_; }; //---------------------------------------------------------------------------------------------------------------------- OdbToRequest::OdbToRequest(const std::string& verb, bool one, bool constant) : verb_(verb), one_(one), onlyConstantColumns_(constant) { LOG_DEBUG_LIB(LibMetkit) << "OdbToRequest one: " << one << " constant: " << constant << std::endl; } OdbToRequest::~OdbToRequest() {} std::vector OdbToRequest::odbToRequest(DataHandle& dh) const { LOG_DEBUG_LIB(LibMetkit) << "OdbToRequest::odbToRequest() dh: " << dh << std::endl; Reader reader(dh, false); Frame frame; std::vector requests; while ((frame = reader.next())) { Span span = frame.span(OdbMetadataDecoder::columnNames(), onlyConstantColumns_); MarsRequest r(verb_); MarsRequestSetter setter(r); OdbMetadataDecoder decoder(setter, {}, verb_); span.visit(decoder); if (one_ and requests.size()) { requests.back().merge(r); } else { requests.push_back(r); } } return requests; } //---------------------------------------------------------------------------------------------------------------------- } // namespace odb } // namespace metkit metkit-1.16.0/src/metkit/odb/OdbToRequest.h000066400000000000000000000025731513171467200204730ustar00rootroot00000000000000/* * (C) Copyright 1996-2012 ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ #ifndef metkit_OdbToRequest_H #define metkit_OdbToRequest_H #include #include #include "eckit/filesystem/PathName.h" #include "eckit/io/Length.h" #include "eckit/io/Offset.h" #include "metkit/mars/MarsRequest.h" namespace eckit { class DataHandle; } namespace metkit { using namespace mars; namespace odb { //---------------------------------------------------------------------------------------------------------------------- class OdbToRequest { public: // methods OdbToRequest(const std::string& verb, bool one, bool constant); ~OdbToRequest(); std::vector odbToRequest(eckit::DataHandle& dh) const; private: // members std::string verb_ = "retrieve"; bool one_ = false; // bool mergeSimilarBlocks_ = false; // unused bool onlyConstantColumns_ = false; }; //---------------------------------------------------------------------------------------------------------------------- } // namespace odb } // namespace metkit #endif metkit-1.16.0/src/metkit/pointdb/000077500000000000000000000000001513171467200166265ustar00rootroot00000000000000metkit-1.16.0/src/metkit/pointdb/DataSource.cc000066400000000000000000000016151513171467200211720ustar00rootroot00000000000000/* * (C) Copyright 1996-2013 ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ #include "metkit/pointdb/DataSource.h" #include "metkit/pointdb/PointIndex.h" namespace metkit { namespace pointdb { DataSource::~DataSource() {} size_t DataSource::batch() const { return 0; } void PointResult::print(std::ostream& s) const { s << "PointResult[lat=" << lat_ << ",lon=" << lon_ << ",value=" << value_ << "]"; } //---------------------------------------------------------------------------------------------------------------------- } // namespace pointdb } // namespace metkit metkit-1.16.0/src/metkit/pointdb/DataSource.h000066400000000000000000000036631513171467200210410ustar00rootroot00000000000000/* * (C) Copyright 1996-2013 ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ #ifndef metkit_DataSource_H #define metkit_DataSource_H #include #include #include "eckit/memory/NonCopyable.h" namespace eckit { class JSON; class Value; } // namespace eckit namespace metkit { class MarsRequest; namespace pointdb { class DataSource; struct PointResult { double value_; double lat_; double lon_; const DataSource* source_; // Warning, the source must have a longer life time as the result void print(std::ostream& s) const; friend std::ostream& operator<<(std::ostream& s, const PointResult& f) { f.print(s); return s; } }; class DataSourceHandler { public: virtual void handle(DataSource*) = 0; }; class DataSource : public eckit::NonCopyable { public: virtual ~DataSource(); virtual PointResult extract(double lat, double lon) const = 0; // Encode a MARS-like request representing the field virtual const std::map& request() const = 0; // A key to group source togther, e.g. sources poiting to the same file virtual std::string groupKey() const = 0; // A key to sort sources of the same group, e.g. offset in the file virtual std::string sortKey() const = 0; // Used to throw away requests in case of restarted transactions virtual size_t batch() const; private: virtual void print(std::ostream& s) const = 0; friend std::ostream& operator<<(std::ostream& s, const DataSource& f) { f.print(s); return s; } }; } // namespace pointdb } // namespace metkit #endif metkit-1.16.0/src/metkit/pointdb/FieldIndexer.cc000066400000000000000000000012501513171467200214750ustar00rootroot00000000000000/* * (C) Copyright 1996- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ #include "metkit/pointdb/FieldIndexer.h" namespace metkit { namespace pointdb { FieldIndexer::~FieldIndexer() {} //---------------------------------------------------------------------------------------------------------------------- } // namespace pointdb } // namespace metkit metkit-1.16.0/src/metkit/pointdb/FieldIndexer.h000066400000000000000000000042661513171467200213510ustar00rootroot00000000000000/* * (C) Copyright 1996- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ // File FieldIndex.h // Baudouin Raoult - ECMWF Oct 19 #ifndef metkit_FieldIndex_H #define metkit_FieldIndex_H #include #include namespace eckit { class Value; class JSON; } // namespace eckit namespace metkit { class MarsRequest; namespace pointdb { class DataSource; class DataSourceHandler; //---------------------------------------------------------------------------------------------------------------------- struct FieldIndexerStatus { size_t count_; size_t batch_; FieldIndexerStatus(size_t count, size_t batch) : count_(count), batch_(batch) {} }; class FieldIndexer { public: // -- Exceptions // None // -- Contructors // -- Destructor virtual ~FieldIndexer(); // -- Convertors // None // -- Operators // None // -- Methods virtual FieldIndexerStatus lookup(const eckit::Value&, DataSourceHandler&) const = 0; // -- Overridden methods // None // -- Class members // None // -- Class methods // None // Uncomment for persistent, remove otherwise protected: // -- Members // None // -- Methods virtual void print(std::ostream& s) const = 0; // -- Overridden methods // None // -- Class members // None // -- Class methods // None private: // No copy allowed // -- Members // -- Methods // None // -- Overridden methods // None // -- Class members // None // -- Class methods // None // -- Friends friend std::ostream& operator<<(std::ostream& s, const FieldIndexer& p) { p.print(s); return s; } }; //---------------------------------------------------------------------------------------------------------------------- } // namespace pointdb } // namespace metkit #endif metkit-1.16.0/src/metkit/pointdb/GribDataSource.cc000066400000000000000000000024501513171467200217740ustar00rootroot00000000000000/* * (C) Copyright 1996-2013 ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ #include "metkit/pointdb/GribDataSource.h" #include "metkit/pointdb/GribFieldInfo.h" namespace metkit { namespace pointdb { PointResult GribDataSource::extract(double lat, double lon) const { PointResult result; // ASSERT(!source.needInterpolation()); PointIndex& pi = PointIndex::lookUp(geographyHash()); PointIndex::NodeInfo n = pi.nearestNeighbour(lat, lon); result.lat_ = n.point().lat(); result.lon_ = n.point().lon(); result.value_ = value(n.point().payload_); result.source_ = this; return result; } double GribDataSource::value(size_t index) const { return info().value(*this, index); } std::string GribDataSource::geographyHash() const { return info().geographyHash(); } //---------------------------------------------------------------------------------------------------------------------- } // namespace pointdb } // namespace metkit metkit-1.16.0/src/metkit/pointdb/GribDataSource.h000066400000000000000000000021671513171467200216430ustar00rootroot00000000000000/* * (C) Copyright 1996-2013 ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ #ifndef metkit_GribDataSource_H #define metkit_GribDataSource_H #include "metkit/pointdb/DataSource.h" #include "metkit/pointdb/PointIndex.h" namespace eckit { class Offset; } namespace metkit { namespace pointdb { class GribFieldInfo; class GribDataSource : public DataSource { public: virtual PointResult extract(double lat, double lon) const; private: virtual double value(size_t index) const; virtual std::string geographyHash() const; virtual eckit::Offset seek(const eckit::Offset&) const = 0; virtual long read(void*, long) const = 0; virtual const GribFieldInfo& info() const = 0; friend class GribFieldInfo; }; } // namespace pointdb } // namespace metkit #endif metkit-1.16.0/src/metkit/pointdb/GribFieldInfo.cc000066400000000000000000000131331513171467200216010ustar00rootroot00000000000000/* * (C) Copyright 1996-2013 ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ #include "metkit/pointdb/GribFieldInfo.h" #include #include "metkit/codes/GribAccessor.h" #include "metkit/pointdb/GribDataSource.h" using namespace eckit; using namespace metkit::grib; extern "C" { unsigned long grib_decode_unsigned_long(const unsigned char* p, long* offset, int bits); double grib_power(long s, long n); } namespace metkit { namespace pointdb { static GribAccessor bitmapPresent("bitmapPresent"); static GribAccessor binaryScaleFactor("binaryScaleFactor"); static GribAccessor decimalScaleFactor("decimalScaleFactor"); static GribAccessor bitsPerValue("bitsPerValue"); static GribAccessor referenceValue("referenceValue"); static GribAccessor offsetBeforeData("offsetBeforeData"); static GribAccessor offsetBeforeBitmap("offsetBeforeBitmap"); static GribAccessor numberOfValues("numberOfValues"); static GribAccessor numberOfDataPoints("numberOfDataPoints"); static GribAccessor sphericalHarmonics("sphericalHarmonics"); static Mutex mutex; #define MISSING 9999 static int bits[65536] = { #include "metkit/pointdb/bits.h" }; static uint64_t masks[64] = { #include "metkit/pointdb/masks.h" }; static inline int count_bits(unsigned long long n) { return bits[n & 0xffffu] + bits[(n >> 16) & 0xffffu] + bits[(n >> 32) & 0xffffu] + bits[(n >> 48) & 0xffffu]; } GribFieldInfo::GribFieldInfo() : referenceValue_(0), binaryScaleFactor_(0), decimalScaleFactor_(0), bitsPerValue_(0), offsetBeforeData_(0), offsetBeforeBitmap_(0), numberOfValues_(0), numberOfDataPoints_(0), sphericalHarmonics_(0) {} void GribFieldInfo::update(const GribHandle& h) { binaryScaleFactor_ = binaryScaleFactor(h); decimalScaleFactor_ = decimalScaleFactor(h); bitsPerValue_ = bitsPerValue(h); referenceValue_ = referenceValue(h); offsetBeforeData_ = offsetBeforeData(h); numberOfDataPoints_ = numberOfDataPoints(h); numberOfValues_ = numberOfValues(h); sphericalHarmonics_ = sphericalHarmonics(h); if (bitmapPresent(h)) offsetBeforeBitmap_ = offsetBeforeBitmap(h); else offsetBeforeBitmap_ = 0; if (!sphericalHarmonics_) geographyHash_ = h.geographyHash(); } void GribFieldInfo::print(std::ostream& s) const { s << "GribFieldInfo["; s << "binaryScaleFactor=" << binaryScaleFactor_; s << ",decimalScaleFactor=" << decimalScaleFactor_; s << ",bitsPerValue=" << bitsPerValue_; s << ",referenceValue=" << referenceValue_; s << ",offsetBeforeData=" << offsetBeforeData_; s << ",numberOfDataPoints=" << numberOfDataPoints_; s << ",numberOfValues=" << numberOfValues_; s << ",offsetBeforeBitmap=" << offsetBeforeBitmap_; s << ",sphericalHarmonics=" << sphericalHarmonics_; s << ",geographyHash=" << geographyHash_; s << "]"; } double GribFieldInfo::interpolate(GribDataSource& f, double& lat, double& lon) const { NOTIMP; } double GribFieldInfo::value(const GribDataSource& f, size_t index) const { unsigned char buf[8]; if (bitsPerValue_ == 0) return referenceValue_; ASSERT(!sphericalHarmonics_); if (offsetBeforeBitmap_) { ASSERT(index < numberOfDataPoints_); Log::info() << "offsetBeforeBitmap_ " << offsetBeforeBitmap_ << ",index " << index << std::endl; Offset offset(offsetBeforeBitmap_); ASSERT(f.seek(offset) == offset); size_t count = 0; uint64_t n; ASSERT(sizeof(n) == 8); size_t skip = index / (sizeof(n) * 8); Log::info() << "Read " << skip << " words" << std::endl; for (size_t i = 0; i < skip; ++i) { ASSERT(f.read(&n, sizeof(n)) == sizeof(n)); count += count_bits(n); } Log::info() << "Count " << count << std::endl; size_t pos = index % (sizeof(n) * 8); Log::info() << "Read last bits, " << pos << std::endl; ASSERT(f.read(&n, sizeof(n)) == sizeof(n)); Log::info() << "Read last bits, " << pos << ", before mask " << std::bitset<64>(n) << std::endl; n &= masks[pos]; Log::info() << "Read last bits, " << pos << ", after mask " << std::bitset<64>(n) << ", bits=" << count_bits(n) << std::endl; count += count_bits(n); Log::info() << "Count " << count << std::endl; n = (n >> (64 - pos)) & 1; if (!n) { return MISSING; } ASSERT(count); index = count - 1; } Log::info() << "index " << index << ", numberOfValues " << numberOfValues_ << std::endl; ASSERT(index < numberOfValues_); { Offset offset = off_t(offsetBeforeData_) + off_t(index * bitsPerValue_ / 8); ASSERT(f.seek(offset) == offset); long len = (bitsPerValue_ + 7) / 8; ASSERT(f.read(buf, len) == len); } long bitp = (index * bitsPerValue_) % 8; unsigned long p = grib_decode_unsigned_long(buf, &bitp, bitsPerValue_); // TODO: store the precomputed values double s = grib_power(binaryScaleFactor_, 2); double d = grib_power(-decimalScaleFactor_, 10); double v = (double)(((p * s) + referenceValue_) * d); return v; } } // namespace pointdb } // namespace metkit metkit-1.16.0/src/metkit/pointdb/GribFieldInfo.h000066400000000000000000000032261513171467200214450ustar00rootroot00000000000000/* * (C) Copyright 1996-2013 ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ #ifndef FieldInfoData_H #define FieldInfoData_H #include "eckit/io/Length.h" #include "eckit/io/Offset.h" #include "eckit/types/FixedString.h" namespace eckit { class PathName; } namespace metkit { namespace grib { class GribHandle; } namespace pointdb { class GribDataSource; class GribFieldInfo { public: GribFieldInfo(); std::string geographyHash() const { return geographyHash_; } bool ready() const { return numberOfValues_ > 0; } void update(const grib::GribHandle& h); double value(const GribDataSource&, size_t index) const; bool useInterpolation() const { return sphericalHarmonics_ != 0; } double interpolate(GribDataSource&, double& lat, double& lon) const; private: double referenceValue_; long binaryScaleFactor_; long decimalScaleFactor_; unsigned long bitsPerValue_; unsigned long offsetBeforeData_; unsigned long offsetBeforeBitmap_; unsigned long numberOfValues_; unsigned long numberOfDataPoints_; long sphericalHarmonics_; eckit::FixedString<32> geographyHash_; void print(std::ostream&) const; friend std::ostream& operator<<(std::ostream& s, const GribFieldInfo& f) { f.print(s); return s; } }; } // namespace pointdb } // namespace metkit #endif metkit-1.16.0/src/metkit/pointdb/GribHandleDataSource.cc000066400000000000000000000067321513171467200231170ustar00rootroot00000000000000/* * (C) Copyright 1996-2013 ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ #include #include "eckit/exception/Exceptions.h" #include "eckit/filesystem/PathName.h" #include "eckit/io/Buffer.h" #include "eckit/io/DataHandle.h" #include "eckit/io/PooledHandle.h" #include "eckit/io/StdFile.h" #include "eckit/utils/MD5.h" #include "metkit/codes/GribHandle.h" #include "metkit/pointdb/GribFieldInfo.h" #include "metkit/pointdb/GribHandleDataSource.h" #include "metkit/pointdb/PointIndex.h" namespace metkit { namespace pointdb { GribHandleDataSource::GribHandleDataSource(const eckit::PathName& path, const eckit::Offset& offset) : handle_(path.fileHandle()), ownsHandle_(true), opened_(false), offset_(offset) {} GribHandleDataSource::GribHandleDataSource(eckit::DataHandle& handle, const eckit::Offset& offset) : handle_(&handle), ownsHandle_(false), opened_(false), offset_(offset) {} GribHandleDataSource::GribHandleDataSource(eckit::DataHandle* handle, const eckit::Offset& offset) : handle_(handle), ownsHandle_(true), opened_(false), offset_(offset) { ASSERT(handle_); } GribHandleDataSource::~GribHandleDataSource() { if (opened_) { handle_->close(); } if (ownsHandle_) { delete handle_; } } void GribHandleDataSource::open() const { if (!opened_) { handle_->openForRead(); opened_ = true; } } eckit::Offset GribHandleDataSource::seek(const eckit::Offset& offset) const { open(); eckit::Offset pos = handle_->seek(offset_ + offset); return (long long)pos - (long long)offset_; } long GribHandleDataSource::read(void* buffer, long len) const { open(); return handle_->read(buffer, len); } const GribFieldInfo& GribHandleDataSource::info() const { if (!info_.ready()) { eckit::MD5 md5; md5 << *handle_; md5 << static_cast(offset_); eckit::PathName cache = PointIndex::cachePath("grib-info", md5); if (cache.exists()) { eckit::StdFile f(cache); ASSERT(::fread(&info_, sizeof(info_), 1, f) == 1); f.close(); } else { open(); handle_->seek(offset_); grib::GribHandle h(*handle_); info_.update(h); cache.dirName().mkdir(); eckit::StdFile f(cache, "w"); ASSERT(::fwrite(&info_, sizeof(info_), 1, f) == 1); f.close(); PointIndex::cache(h); } } return info_; } void GribHandleDataSource::print(std::ostream& s) const { s << "GribHandleDataSource[" << *handle_ << "]" << std::endl; } const std::map& GribHandleDataSource::request() const { NOTIMP; // Implement a grib2request like function } std::string GribHandleDataSource::groupKey() const { eckit::MD5 md5; md5 << *handle_; return md5; } std::string GribHandleDataSource::sortKey() const { std::ostringstream oss; oss << std::setfill('0') << std::setw(20) << offset_; return oss.str(); } //---------------------------------------------------------------------------------------------------------------------- } // namespace pointdb } // namespace metkit metkit-1.16.0/src/metkit/pointdb/GribHandleDataSource.h000066400000000000000000000031131513171467200227470ustar00rootroot00000000000000/* * (C) Copyright 1996-2013 ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ #ifndef metkit_GribHandleDataSource_H #define metkit_GribHandleDataSource_H #include "metkit/pointdb/GribDataSource.h" #include "metkit/pointdb/GribFieldInfo.h" namespace eckit { class DataHandle; } namespace metkit { namespace pointdb { class GribHandleDataSource : public GribDataSource { public: GribHandleDataSource(const eckit::PathName&, const eckit::Offset& = 0); GribHandleDataSource(eckit::DataHandle&, const eckit::Offset& = 0); GribHandleDataSource(eckit::DataHandle*, const eckit::Offset& = 0); ~GribHandleDataSource(); private: mutable eckit::DataHandle* handle_; bool ownsHandle_; mutable bool opened_; mutable GribFieldInfo info_; eckit::Offset offset_; virtual eckit::Offset seek(const eckit::Offset&) const override; virtual long read(void*, long) const override; virtual const GribFieldInfo& info() const override; virtual void print(std::ostream& s) const override; virtual const std::map& request() const override; virtual std::string groupKey() const override; virtual std::string sortKey() const override; void open() const; }; } // namespace pointdb } // namespace metkit #endif metkit-1.16.0/src/metkit/pointdb/PointIndex.cc000066400000000000000000000102411513171467200212140ustar00rootroot00000000000000/* * (C) Copyright 1996-2013 ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ // #include "eckit/exception/Exceptions.h" // #include "eckit/thread/Mutex.h" // #include "eckit/os/Stat.h" // #include "eckit/log/Timer.h" #include "metkit/pointdb/PointIndex.h" #include "eckit/thread/AutoLock.h" #include "metkit/codes/GribHandle.h" #include "metkit/codes/GribIterator.h" // #include "eckit/io/StdFile.h" #include "eckit/config/Resource.h" // #include "eccodes.h" using namespace eckit; namespace metkit { namespace pointdb { static Mutex mutex; static std::set done_; static std::map cache_; eckit::PathName PointIndex::cachePath(const std::string& dir, const std::string& name) { static eckit::PathName pointdbCachePath = eckit::Resource("pointdbCachePath", "~/pointdb"); return pointdbCachePath / dir / name; } std::string PointIndex::cache(const metkit::grib::GribHandle& h) { double lat, lon, value; std::string md5 = h.geographyHash(); AutoLock lock(mutex); if (done_.find(md5) != done_.end()) { return md5; } eckit::PathName path = cachePath("grids", md5 + ".kdtree"); if (path.exists()) { done_.insert(md5); return md5; } path.dirName().mkdir(); size_t v = h.getDataValuesSize(); std::vector p; p.reserve(v); metkit::grib::GribIterator iter(h); size_t j = 0; while (iter.next(lat, lon, value)) { while (lon < 0) lon += 360; while (lon >= 360) lon -= 360; // ASSERT(lat >= -90 && lat <= 90); p.push_back(Point(lat, lon, j)); j++; } PathName tmp = cachePath("grids", md5 + ".tmp"); tmp.unlink(); Tree* tree = new Tree(tmp, p.size(), 0); tree->build(p.begin(), p.end()); // PathName dump(std::string("/tmp/cache/pointdb/") + md5 + ".dump"); // StdFile f(dump, "w"); // codes_dump_content(h, f, "debug", 0, 0); // f.close(); PathName grib = cachePath("grids", md5 + ".grib"); h.write(grib); PathName::rename(tmp, path); cache_[md5] = new PointIndex(path, tree); done_.insert(md5); return md5; } PointIndex& PointIndex::lookUp(const std::string& md5) { AutoLock lock(mutex); std::map::iterator k = cache_.find(md5); if (k == cache_.end()) { eckit::PathName path = cachePath("grids", md5 + ".kdtree"); if (!path.exists()) { Log::warning() << path << " does not exists" << std::endl; PathName grib = cachePath("grids", md5 + ".grib"); if (grib.exists()) { Log::warning() << "Rebuilding index from " << grib << std::endl; metkit::grib::GribHandle h(grib); ASSERT(cache(h) == md5); } } Log::warning() << "Loading " << path << std::endl; PointIndex* p = new PointIndex(path); cache_[md5] = p; return *p; } return *(*k).second; } PointIndex::PointIndex(const PathName& path, PointIndex::Tree* tree) : path_(path), tree_(tree) { if (!tree) { Log::info() << "Load tree " << path << std::endl; ASSERT(path.exists()); tree_.reset(new Tree(path, 0, 0)); } } PointIndex::~PointIndex() { // TODO } PointIndex::NodeInfo PointIndex::nearestNeighbour(double lat, double lon) { Point p(lat, lon, 0); std::map::iterator k; { AutoLock lock(mutex_); k = last_.find(p); if (k != last_.end()) return (*k).second; } NodeInfo n; { Timer timer("Find nearest"); n = tree_->nearestNeighbour(p); } { AutoLock lock(mutex_); if (last_.size() >= 4096) last_.clear(); last_[p] = n; } return n; } } // namespace pointdb } // namespace metkit metkit-1.16.0/src/metkit/pointdb/PointIndex.h000066400000000000000000000057031513171467200210650ustar00rootroot00000000000000/* * (C) Copyright 1996-2013 ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ #ifndef PointIndex_H #define PointIndex_H // #include #include // #include "eckit/eckit.h" // #include "eckit/filesystem/PathName.h" #include "eckit/container/KDTree.h" #include "eckit/geometry/Point3.h" namespace metkit { namespace grib { class GribHandle; } namespace pointdb { struct LLPoint2 : public eckit::geometry::Point3 { double lat_; double lon_; size_t payload_; double lat() const { return lat_; } double lon() const { return lon_; } size_t payload() const { return payload_; } const LLPoint2& point() const { return *this; } LLPoint2() : eckit::geometry::Point3() {} LLPoint2(double lat, double lon, size_t index) : eckit::geometry::Point3(), lat_(lat), lon_(lon) { // See http://en.wikipedia.org/wiki/Geodetic_system#From_geodetic_to_ECEF payload_ = index; double& X = x_[0]; double& Y = x_[1]; double& Z = x_[2]; double h = 0; // Altitude const double earthRadius = 6378137.0; double a = earthRadius; // 6378137.0 ; // WGS84 semi-major axis double e2 = 0; // 6.69437999014E-3; // WGS84 first numerical eccentricity sqared double phi = lat / 180.0 * M_PI; double lambda = lon / 180.0 * M_PI; double cos_phi = cos(phi); double sin_phi = sin(phi); double cos_lambda = cos(lambda); double sin_lambda = sin(lambda); double N_phi = a / sqrt(1 - e2 * sin_phi * sin_phi); X = (N_phi + h) * cos_phi * cos_lambda; Y = (N_phi + h) * cos_phi * sin_lambda; Z = (N_phi * (1 - e2) + h) * sin_phi; } friend std::ostream& operator<<(std::ostream& s, const LLPoint2& p) { s << '(' << p.lat_ << "," << p.lon_ << ' ' << p.payload_ << ')'; return s; } }; struct PointIndexTraits { using Point = LLPoint2; using Payload = size_t; }; class PointIndex { public: typedef eckit::KDTreeMapped Tree; typedef Tree::Point Point; typedef Tree::NodeInfo NodeInfo; NodeInfo nearestNeighbour(double lat, double lon); static PointIndex& lookUp(const std::string& md5); static std::string cache(const metkit::grib::GribHandle& h); static eckit::PathName cachePath(const std::string& dir, const std::string& name); private: PointIndex(const eckit::PathName&, Tree* tree = 0); ~PointIndex(); eckit::PathName path_; std::unique_ptr tree_; std::map last_; eckit::Mutex mutex_; }; } // namespace pointdb } // namespace metkit #endif metkit-1.16.0/src/metkit/pointdb/bits.h000066400000000000000000006540711513171467200177550ustar00rootroot00000000000000/* * (C) Copyright 1996-2013 ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 10, 11, 11, 12, 11, 12, 12, 13, 11, 12, 12, 13, 12, 13, 13, 14, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 10, 11, 11, 12, 11, 12, 12, 13, 11, 12, 12, 13, 12, 13, 13, 14, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 10, 11, 11, 12, 11, 12, 12, 13, 11, 12, 12, 13, 12, 13, 13, 14, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 10, 11, 11, 12, 11, 12, 12, 13, 11, 12, 12, 13, 12, 13, 13, 14, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 10, 11, 11, 12, 11, 12, 12, 13, 11, 12, 12, 13, 12, 13, 13, 14, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 10, 11, 11, 12, 11, 12, 12, 13, 11, 12, 12, 13, 12, 13, 13, 14, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 10, 11, 11, 12, 11, 12, 12, 13, 11, 12, 12, 13, 12, 13, 13, 14, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 10, 11, 11, 12, 11, 12, 12, 13, 11, 12, 12, 13, 12, 13, 13, 14, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 10, 11, 11, 12, 11, 12, 12, 13, 11, 12, 12, 13, 12, 13, 13, 14, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 10, 11, 11, 12, 11, 12, 12, 13, 11, 12, 12, 13, 12, 13, 13, 14, 10, 11, 11, 12, 11, 12, 12, 13, 11, 12, 12, 13, 12, 13, 13, 14, 11, 12, 12, 13, 12, 13, 13, 14, 12, 13, 13, 14, 13, 14, 14, 15, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 10, 11, 11, 12, 11, 12, 12, 13, 11, 12, 12, 13, 12, 13, 13, 14, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 10, 11, 11, 12, 11, 12, 12, 13, 11, 12, 12, 13, 12, 13, 13, 14, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 10, 11, 11, 12, 11, 12, 12, 13, 11, 12, 12, 13, 12, 13, 13, 14, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 10, 11, 11, 12, 11, 12, 12, 13, 11, 12, 12, 13, 12, 13, 13, 14, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 10, 11, 11, 12, 11, 12, 12, 13, 11, 12, 12, 13, 12, 13, 13, 14, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 10, 11, 11, 12, 11, 12, 12, 13, 11, 12, 12, 13, 12, 13, 13, 14, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 10, 11, 11, 12, 11, 12, 12, 13, 11, 12, 12, 13, 12, 13, 13, 14, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 10, 11, 11, 12, 11, 12, 12, 13, 11, 12, 12, 13, 12, 13, 13, 14, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 10, 11, 11, 12, 11, 12, 12, 13, 11, 12, 12, 13, 12, 13, 13, 14, 10, 11, 11, 12, 11, 12, 12, 13, 11, 12, 12, 13, 12, 13, 13, 14, 11, 12, 12, 13, 12, 13, 13, 14, 12, 13, 13, 14, 13, 14, 14, 15, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 10, 11, 11, 12, 11, 12, 12, 13, 11, 12, 12, 13, 12, 13, 13, 14, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 10, 11, 11, 12, 11, 12, 12, 13, 11, 12, 12, 13, 12, 13, 13, 14, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 10, 11, 11, 12, 11, 12, 12, 13, 11, 12, 12, 13, 12, 13, 13, 14, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 10, 11, 11, 12, 11, 12, 12, 13, 11, 12, 12, 13, 12, 13, 13, 14, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 10, 11, 11, 12, 11, 12, 12, 13, 11, 12, 12, 13, 12, 13, 13, 14, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 10, 11, 11, 12, 11, 12, 12, 13, 11, 12, 12, 13, 12, 13, 13, 14, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 10, 11, 11, 12, 11, 12, 12, 13, 11, 12, 12, 13, 12, 13, 13, 14, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 10, 11, 11, 12, 11, 12, 12, 13, 11, 12, 12, 13, 12, 13, 13, 14, 10, 11, 11, 12, 11, 12, 12, 13, 11, 12, 12, 13, 12, 13, 13, 14, 11, 12, 12, 13, 12, 13, 13, 14, 12, 13, 13, 14, 13, 14, 14, 15, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 10, 11, 11, 12, 11, 12, 12, 13, 11, 12, 12, 13, 12, 13, 13, 14, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 10, 11, 11, 12, 11, 12, 12, 13, 11, 12, 12, 13, 12, 13, 13, 14, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 10, 11, 11, 12, 11, 12, 12, 13, 11, 12, 12, 13, 12, 13, 13, 14, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 10, 11, 11, 12, 11, 12, 12, 13, 11, 12, 12, 13, 12, 13, 13, 14, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 10, 11, 11, 12, 11, 12, 12, 13, 11, 12, 12, 13, 12, 13, 13, 14, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 10, 11, 11, 12, 11, 12, 12, 13, 11, 12, 12, 13, 12, 13, 13, 14, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 10, 11, 11, 12, 11, 12, 12, 13, 11, 12, 12, 13, 12, 13, 13, 14, 10, 11, 11, 12, 11, 12, 12, 13, 11, 12, 12, 13, 12, 13, 13, 14, 11, 12, 12, 13, 12, 13, 13, 14, 12, 13, 13, 14, 13, 14, 14, 15, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 10, 11, 11, 12, 11, 12, 12, 13, 11, 12, 12, 13, 12, 13, 13, 14, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 10, 11, 11, 12, 11, 12, 12, 13, 11, 12, 12, 13, 12, 13, 13, 14, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 10, 11, 11, 12, 11, 12, 12, 13, 11, 12, 12, 13, 12, 13, 13, 14, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 10, 11, 11, 12, 11, 12, 12, 13, 11, 12, 12, 13, 12, 13, 13, 14, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 10, 11, 11, 12, 11, 12, 12, 13, 11, 12, 12, 13, 12, 13, 13, 14, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 10, 11, 11, 12, 11, 12, 12, 13, 11, 12, 12, 13, 12, 13, 13, 14, 10, 11, 11, 12, 11, 12, 12, 13, 11, 12, 12, 13, 12, 13, 13, 14, 11, 12, 12, 13, 12, 13, 13, 14, 12, 13, 13, 14, 13, 14, 14, 15, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 10, 11, 11, 12, 11, 12, 12, 13, 11, 12, 12, 13, 12, 13, 13, 14, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 10, 11, 11, 12, 11, 12, 12, 13, 11, 12, 12, 13, 12, 13, 13, 14, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 10, 11, 11, 12, 11, 12, 12, 13, 11, 12, 12, 13, 12, 13, 13, 14, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 10, 11, 11, 12, 11, 12, 12, 13, 11, 12, 12, 13, 12, 13, 13, 14, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 10, 11, 11, 12, 11, 12, 12, 13, 11, 12, 12, 13, 12, 13, 13, 14, 10, 11, 11, 12, 11, 12, 12, 13, 11, 12, 12, 13, 12, 13, 13, 14, 11, 12, 12, 13, 12, 13, 13, 14, 12, 13, 13, 14, 13, 14, 14, 15, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 8, 9, 8, 9, 9, 10, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 10, 11, 11, 12, 11, 12, 12, 13, 11, 12, 12, 13, 12, 13, 13, 14, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 10, 11, 11, 12, 11, 12, 12, 13, 11, 12, 12, 13, 12, 13, 13, 14, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 10, 11, 11, 12, 11, 12, 12, 13, 11, 12, 12, 13, 12, 13, 13, 14, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 10, 11, 11, 12, 11, 12, 12, 13, 11, 12, 12, 13, 12, 13, 13, 14, 10, 11, 11, 12, 11, 12, 12, 13, 11, 12, 12, 13, 12, 13, 13, 14, 11, 12, 12, 13, 12, 13, 13, 14, 12, 13, 13, 14, 13, 14, 14, 15, 7, 8, 8, 9, 8, 9, 9, 10, 8, 9, 9, 10, 9, 10, 10, 11, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 10, 11, 11, 12, 11, 12, 12, 13, 11, 12, 12, 13, 12, 13, 13, 14, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 10, 11, 11, 12, 11, 12, 12, 13, 11, 12, 12, 13, 12, 13, 13, 14, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 10, 11, 11, 12, 11, 12, 12, 13, 11, 12, 12, 13, 12, 13, 13, 14, 10, 11, 11, 12, 11, 12, 12, 13, 11, 12, 12, 13, 12, 13, 13, 14, 11, 12, 12, 13, 12, 13, 13, 14, 12, 13, 13, 14, 13, 14, 14, 15, 8, 9, 9, 10, 9, 10, 10, 11, 9, 10, 10, 11, 10, 11, 11, 12, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 10, 11, 11, 12, 11, 12, 12, 13, 11, 12, 12, 13, 12, 13, 13, 14, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 10, 11, 11, 12, 11, 12, 12, 13, 11, 12, 12, 13, 12, 13, 13, 14, 10, 11, 11, 12, 11, 12, 12, 13, 11, 12, 12, 13, 12, 13, 13, 14, 11, 12, 12, 13, 12, 13, 13, 14, 12, 13, 13, 14, 13, 14, 14, 15, 9, 10, 10, 11, 10, 11, 11, 12, 10, 11, 11, 12, 11, 12, 12, 13, 10, 11, 11, 12, 11, 12, 12, 13, 11, 12, 12, 13, 12, 13, 13, 14, 10, 11, 11, 12, 11, 12, 12, 13, 11, 12, 12, 13, 12, 13, 13, 14, 11, 12, 12, 13, 12, 13, 13, 14, 12, 13, 13, 14, 13, 14, 14, 15, 10, 11, 11, 12, 11, 12, 12, 13, 11, 12, 12, 13, 12, 13, 13, 14, 11, 12, 12, 13, 12, 13, 13, 14, 12, 13, 13, 14, 13, 14, 14, 15, 11, 12, 12, 13, 12, 13, 13, 14, 12, 13, 13, 14, 13, 14, 14, 15, 12, 13, 13, 14, 13, 14, 14, 15, 13, 14, 14, 15, 14, 15, 15, 16, metkit-1.16.0/src/metkit/pointdb/masks.h000066400000000000000000000032551513171467200201220ustar00rootroot00000000000000/* * (C) Copyright 1996-2013 ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ 0x0, 0x8000000000000000, 0xc000000000000000, 0xe000000000000000, 0xf000000000000000, 0xf800000000000000, 0xfc00000000000000, 0xfe00000000000000, 0xff00000000000000, 0xff80000000000000, 0xffc0000000000000, 0xffe0000000000000, 0xfff0000000000000, 0xfff8000000000000, 0xfffc000000000000, 0xfffe000000000000, 0xffff000000000000, 0xffff800000000000, 0xffffc00000000000, 0xffffe00000000000, 0xfffff00000000000, 0xfffff80000000000, 0xfffffc0000000000, 0xfffffe0000000000, 0xffffff0000000000, 0xffffff8000000000, 0xffffffc000000000, 0xffffffe000000000, 0xfffffff000000000, 0xfffffff800000000, 0xfffffffc00000000, 0xfffffffe00000000, 0xffffffff00000000, 0xffffffff80000000, 0xffffffffc0000000, 0xffffffffe0000000, 0xfffffffff0000000, 0xfffffffff8000000, 0xfffffffffc000000, 0xfffffffffe000000, 0xffffffffff000000, 0xffffffffff800000, 0xffffffffffc00000, 0xffffffffffe00000, 0xfffffffffff00000, 0xfffffffffff80000, 0xfffffffffffc0000, 0xfffffffffffe0000, 0xffffffffffff0000, 0xffffffffffff8000, 0xffffffffffffc000, 0xffffffffffffe000, 0xfffffffffffff000, 0xfffffffffffff800, 0xfffffffffffffc00, 0xfffffffffffffe00, 0xffffffffffffff00, 0xffffffffffffff80, 0xffffffffffffffc0, 0xffffffffffffffe0, 0xfffffffffffffff0, 0xfffffffffffffff8, 0xfffffffffffffffc, 0xfffffffffffffffe, metkit-1.16.0/src/metkit/tool/000077500000000000000000000000001513171467200161445ustar00rootroot00000000000000metkit-1.16.0/src/metkit/tool/MetkitTool.cc000066400000000000000000000055461513171467200205600ustar00rootroot00000000000000/* * (C) Copyright 1996- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ #include "eckit/exception/Exceptions.h" #include "eckit/log/Log.h" #include "eckit/option/CmdArgs.h" #include "eckit/option/SimpleOption.h" #include "eckit/system/Library.h" #include "metkit/config/LibMetkit.h" #include "metkit/tool/MetkitTool.h" using namespace eckit; using namespace eckit::option; namespace metkit { //---------------------------------------------------------------------------------------------------------------------- static MetkitTool* instance_ = nullptr; MetkitTool::MetkitTool(int argc, char** argv) : eckit::Tool(argc, argv, "METKIT_HOME") { ASSERT(instance_ == nullptr); instance_ = this; options_.push_back(new SimpleOption("version", "Prints the version and exits")); options_.push_back(new SimpleOption("porcelain", "Stable output that can be used as input to other tools")); } static void usage(const std::string& tool) { ASSERT(instance_); instance_->usage(tool); } void MetkitTool::run() { LOG_DEBUG_LIB(LibMetkit) << "MetkitTool::run()" << std::endl; CmdArgs args(&metkit::usage, options_, numberOfPositionalArguments(), minimumPositionalArguments()); if (args.has("version")) { auto& log = eckit::Log::info(); using eckit::system::Library; for (const auto& lib_name : Library::list()) { auto& lib = Library::lookup(lib_name); log << lib.name() << " " << lib.version() << " git-sha1:" << lib.gitsha1(8) << " home:" << lib.libraryHome() << std::endl; } return; //< stops processing } init(args); execute(args); finish(args); } void MetkitTool::usage(const std::string& tool) const { Log::info() << "Usage: " << tool << "[-h] [...options...]" << std::endl; } void MetkitTool::init(const eckit::option::CmdArgs& args) { LOG_DEBUG_LIB(LibMetkit) << "MetkitTool::init()" << std::endl; args.get("porcelain", porcelain_); } void MetkitTool::finish(const eckit::option::CmdArgs& args) { LOG_DEBUG_LIB(LibMetkit) << "MetkitTool::finish()" << std::endl; } //---------------------------------------------------------------------------------------------------------------------- MetkitToolException::MetkitToolException(const std::string& w) : Exception(w) {} MetkitToolException::MetkitToolException(const std::string& w, const eckit::CodeLocation& l) : Exception(w, l) {} //---------------------------------------------------------------------------------------------------------------------- } // namespace metkit metkit-1.16.0/src/metkit/tool/MetkitTool.h000066400000000000000000000037501513171467200204150ustar00rootroot00000000000000/* * (C) Copyright 1996- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ /// @file MetkitTool.h /// @author Tiago Quintino /// @date Mar 2020 #ifndef metkit_MetkitTool_H #define metkit_MetkitTool_H #include #include "eckit/exception/Exceptions.h" #include "eckit/runtime/Tool.h" namespace eckit { namespace option { class Option; class CmdArgs; } // namespace option } // namespace eckit namespace metkit { //---------------------------------------------------------------------------------------------------------------------- class MetkitTool : public eckit::Tool { public: // methods MetkitTool(int argc, char** argv); virtual void usage(const std::string& tool) const; protected: // methods using options_t = std::vector; protected: // members options_t options_; bool porcelain_ = false; private: // methods virtual void init(const eckit::option::CmdArgs& args); virtual void execute(const eckit::option::CmdArgs& args) = 0; virtual void finish(const eckit::option::CmdArgs& args); virtual int numberOfPositionalArguments() const { return -1; } virtual int minimumPositionalArguments() const { return -1; } virtual void run(); }; //---------------------------------------------------------------------------------------------------------------------- class MetkitToolException : public eckit::Exception { public: MetkitToolException(const std::string&); MetkitToolException(const std::string&, const eckit::CodeLocation&); }; //---------------------------------------------------------------------------------------------------------------------- } // namespace metkit #endif metkit-1.16.0/src/tools/000077500000000000000000000000001513171467200150325ustar00rootroot00000000000000metkit-1.16.0/src/tools/CMakeLists.txt000066400000000000000000000044651513171467200176030ustar00rootroot00000000000000### provides MARS requests from GRIB files # ecbuild_add_executable( TARGET grib-to-mars-request # CONDITION HAVE_GRIB # SOURCES grib-to-mars-request.cc # INCLUDES # ${ECKIT_INCLUDE_DIRS} # LIBS metkit # ) # ecbuild_add_executable( TARGET grib-blob # CONDITION HAVE_GRIB # SOURCES grib-blob.cc # INCLUDES # ${ECKIT_INCLUDE_DIRS} # LIBS metkit eckit_option eckit # ) # ecbuild_add_executable( TARGET bufr-to-mars-request # CONDITION HAVE_BUFR # SOURCES bufr-to-mars-request.cc # INCLUDES ${ECCODES_INCLUDE_DIRS} ${ECKIT_INCLUDE_DIRS} # LIBS metkit eckit_option eckit eccodes # ) ecbuild_add_executable( TARGET parse-mars-request CONDITION HAVE_GRIB AND HAVE_BUILD_TOOLS SOURCES parse-mars-request.cc INCLUDES ${ECKIT_INCLUDE_DIRS} LIBS metkit eckit_option eckit eccodes NO_AS_NEEDED ) ecbuild_add_executable( TARGET odb-to-request SOURCES odb-to-request.cc CONDITION HAVE_ODB AND HAVE_BUILD_TOOLS INCLUDES ${ECKIT_INCLUDE_DIRS} NO_AS_NEEDED LIBS metkit eckit_option ) ecbuild_add_executable( TARGET bufr-sanity-check SOURCES bufr-sanity-check.cc CONDITION HAVE_BUFR AND HAVE_BUILD_TOOLS INCLUDES ${ECKIT_INCLUDE_DIRS} NO_AS_NEEDED LIBS metkit eckit_option ) ecbuild_add_executable( TARGET mars-archive-script SOURCES mars-archive-script.cc CONDITION HAVE_BUILD_TOOLS INCLUDES ${ECKIT_INCLUDE_DIRS} NO_AS_NEEDED LIBS metkit ) # ecbuild_add_executable( TARGET ncmerge # SOURCES ncmerge.cc # CONDITION HAVE_NETCDF # LIBS metkit NetCDF::NetCDF_C ) if(HAVE_BUILD_TOOLS) list( APPEND tools nccompare.py compare-mars-requests.py ) foreach( _tool ${tools} ) file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/${_tool} DESTINATION ${CMAKE_BINARY_DIR}/bin FILE_PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE ) endforeach() install( FILES ${CMAKE_BINARY_DIR}/bin/compare-mars-requests.py DESTINATION "bin" PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ GROUP_EXECUTE GROUP_READ WORLD_EXECUTE WORLD_READ ) endif() metkit-1.16.0/src/tools/bufr-sanity-check.cc000066400000000000000000000366001513171467200206640ustar00rootroot00000000000000/* * (C) Copyright 1996- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ #include "eccodes.h" #include "eckit/config/Resource.h" #include "eckit/exception/Exceptions.h" #include "eckit/io/FileHandle.h" #include "eckit/option/CmdArgs.h" #include "eckit/option/SimpleOption.h" #include "eckit/types/Date.h" #include "eckit/message/Message.h" #include "eckit/message/Reader.h" #include "metkit/codes/BUFRDecoder.h" #include "metkit/codes/BufrContent.h" #include "metkit/tool/MetkitTool.h" #define WRONG_KEY_LENGTH 65535 using namespace metkit; using namespace eckit; using namespace eckit::option; //---------------------------------------------------------------------------------------------------------------------- enum Status { OK, FIXED, CORRUPTED }; class BufrCheck : public MetkitTool { public: BufrCheck(int argc, char** argv) : MetkitTool(argc, argv) { options_.push_back( new SimpleOption("abort-on-error", "Abort in case of corrupted message, default = true")); options_.push_back( new SimpleOption("patch-on-error", "Try to patch corrupted messages, default = false")); options_.push_back(new SimpleOption("skip-on-error", "Skip corrupted messages, default = false")); options_.push_back(new SimpleOption( "dont-patch-length", "Disable patching of message length in corrupted messages, default = false")); options_.push_back(new SimpleOption( "dont-patch-date", "Disable patching of date/time in corrupted messages, default = false")); options_.push_back(new SimpleOption( "ignore-century", "Disable patching of century in corrupted messages, default = false")); options_.push_back(new SimpleOption("ignore-type", "Ignore inconsistent type/subtype, default = false")); options_.push_back(new SimpleOption("acceptable-time-discrepancy", "Acceptable time discrepancy in seconds, default = 300")); options_.push_back( new SimpleOption("verbose", "Print details of all corrupted messages, default = false")); } virtual ~BufrCheck() {} private: // methods int minimumPositionalArguments() const { return 2; } Status checkMessageLength(const message::Message& msg, int numMessage, eckit::OrderedStringDict& transformation); Status checkSubType(const message::Message& msg, int numMessage); Status checkDate(const message::Message& msg, int numMessage, eckit::OrderedStringDict& transformation); void process(const PathName& input, const PathName& output); virtual void execute(const CmdArgs& args); virtual void init(const CmdArgs& args); virtual void usage(const std::string& tool) const; private: // members bool verbose_; bool abort_; bool patch_; bool skip_; bool ignoreLength_; bool ignoreDate_; bool ignoreCentury_; bool ignoreType_; long timeThreshold_; }; //---------------------------------------------------------------------------------------------------------------------- void BufrCheck::execute(const CmdArgs& args) { process(args(0), args(1)); } void BufrCheck::init(const CmdArgs& args) { patch_ = args.getBool("patch-on-error", false); skip_ = args.getBool("skip-on-error", false); abort_ = args.getBool("abort-on-error", !(patch_ || skip_)); if (abort_ + patch_ + skip_ > 1) { throw UserError( "Inconsistent configuration. You can only specify one of [--abort-on-error, --patch-on-error, " "--skip-on-error]"); } verbose_ = args.getBool("verbose", false); ignoreLength_ = args.getBool("dont-patch-length", false); ignoreDate_ = args.getBool("dont-patch-date", false); ignoreCentury_ = args.getBool("ignore-century", false); ignoreType_ = args.getBool("ignore-type", false); timeThreshold_ = args.getLong("acceptable-time-discrepancy", 300); } void BufrCheck::usage(const std::string& tool) const { Log::info() << "Usage: " << tool << " [options] [input] [output]" << std::endl << std::endl; Log::info() << "Examples:" << std::endl << "=========" << std::endl << std::endl << tool << " input.bufr output.bufr" << std::endl << std::endl << tool << " --skip-on-error --verbose input.bufr output.bufr" << std::endl << std::endl << tool << " --patch-on-error --ignore-century --acceptable-time-discrepancy=600 input.bufr output.bufr" << std::endl << std::endl << tool << " --patch-on-error --dont-patch-date input.bufr output.bufr" << std::endl << std::endl; } Status BufrCheck::checkMessageLength(const message::Message& msg, int numMessage, eckit::OrderedStringDict& transformation) { long totalLength = msg.getLong("totalLength"); long messageLength = msg.getLong("messageLength"); if (totalLength != messageLength && totalLength < WRONG_KEY_LENGTH) { if (verbose_) { Log::error() << "message " << numMessage << ", wrong key length in bufr message " << messageLength << " instead of " << totalLength << std::endl; } if (!patch_ || ignoreLength_) { return Status::CORRUPTED; } else { transformation.emplace_back("messageLength", std::to_string(totalLength)); return Status::FIXED; } } return Status::OK; } Status BufrCheck::checkSubType(const message::Message& msg, int numMessage) { long type = msg.getLong("rdbType"); long subtype = msg.getLong("oldSubtype"); long expectedType; if (codes::BUFRDecoder::typeBySubtype(subtype, expectedType)) { if (type == expectedType) { return Status::OK; } else { if (verbose_ || !ignoreType_) { Log::error() << "message " << numMessage << ", type " << type << " and expected type " << expectedType << " don't match for subtype " << subtype << std::endl; } return Status::CORRUPTED; } } else { if (verbose_ || !ignoreType_) { Log::error() << "message " << numMessage << ", unknown subtype " << subtype << std::endl; } return Status::CORRUPTED; } } Status BufrCheck::checkDate(const message::Message& msg, int numMessage, eckit::OrderedStringDict& transformation) { bool toFix = false; long localYear = msg.getLong("localYear"); long typicalYear = msg.getLong("typicalYear"); if (ignoreCentury_) { typicalYear = (localYear / 100) * 100 + typicalYear % 100; } long typicalMonth = msg.getLong("typicalMonth"); long typicalDay = msg.getLong("typicalDay"); long typicalJulian = 0; try { Date date(typicalYear, typicalMonth, typicalDay); typicalJulian = date.julian(); } catch (...) { if (verbose_) { Log::error() << "message " << numMessage << ", date is weird " << typicalYear << "/" << typicalMonth << "/" << typicalDay << std::endl; } if (!patch_) { return Status::CORRUPTED; } toFix = !ignoreDate_; } long typicalHour = msg.getLong("typicalHour"); long typicalMinute = msg.getLong("typicalMinute"); long typicalSecond = msg.getLong("typicalSecond"); if (typicalHour > 23 || typicalHour < 0 || typicalMinute > 59 || typicalMinute < 0 || typicalSecond > 59 || typicalSecond < 0) { if (verbose_) { Log::error() << "message " << numMessage << ", typical time is weird " << typicalHour << ":" << typicalMinute << ":" << typicalSecond << std::endl; } if (!patch_) { return Status::CORRUPTED; } toFix = !ignoreDate_; } long typicalTime = typicalHour * 3600 + typicalMinute * 60 + typicalSecond; long localMonth = msg.getLong("localMonth"); long localDay = msg.getLong("localDay"); long localJulian = 0; try { Date date(localYear, localMonth, localDay); localJulian = date.julian(); } catch (...) { if (verbose_) { Log::error() << "message " << numMessage << ", date is weird " << localYear << "/" << localMonth << "/" << localDay << std::endl; } return Status::CORRUPTED; } long localHour = msg.getLong("localHour"); long localMinute = msg.getLong("localMinute"); long localSecond = msg.getLong("localSecond"); // we accept localSecond==60 for backward compatibility (filterbufr behaviour) if (localHour > 23 || localHour < 0 || localMinute > 59 || localMinute < 0 || localSecond > 60 || localSecond < 0) { if (verbose_) { Log::error() << "message " << numMessage << ", local time is weird " << localHour << ":" << localMinute << ":" << localSecond << std::endl; } return Status::CORRUPTED; } long localTime = localHour * 3600 + localMinute * 60 + localSecond; if (abs((typicalJulian - localJulian) * 86400 + typicalTime - localTime) > timeThreshold_) { if (verbose_) { Log::error() << "message " << numMessage << ", date-time (" << typicalYear << "/" << typicalMonth << "/" << typicalDay << " " << typicalHour << ":" << typicalMinute << ":" << typicalSecond << ") and local date-time (" << localYear << "/" << localMonth << "/" << localDay << " " << localHour << ":" << localMinute << ":" << localSecond << ") differs" << std::endl; } toFix = !ignoreDate_; } if (toFix) { if (msg.getLong("edition") == 3) { transformation.emplace_back("typicalYearOfCentury", std::to_string(localYear - 2000)); } else { transformation.emplace_back("typicalYear", std::to_string(localYear)); transformation.emplace_back("typicalSecond", std::to_string(localSecond)); } transformation.emplace_back("typicalMonth", std::to_string(localMonth)); transformation.emplace_back("typicalDay", std::to_string(localDay)); transformation.emplace_back("typicalHour", std::to_string(localHour)); transformation.emplace_back("typicalMinute", std::to_string(localMinute)); return Status::FIXED; } return Status::OK; } void BufrCheck::process(const PathName& input, const PathName& output) { message::Reader reader(input); FileHandle out(output.path()); Offset pos; out.openForWrite(0); AutoClose closer(out); int err = 0; void* buffer = NULL; size_t size = 0; bool ok; unsigned int numMessage = 0; unsigned int missingKey = 0; unsigned int messageLength = 0; unsigned int inconsistentSubType = 0; unsigned int inconsistentDate = 0; message::Message rawMsg; do { try { pos = reader.position(); if ((rawMsg = reader.next())) { codes_handle* h = codes_handle_new_from_message(nullptr, rawMsg.data(), rawMsg.length()); if (!h) { throw FailedLibraryCall("eccodes", "codes_handle_new_from_message", "failed to create handle", Here()); } codes::BufrContent* c = new codes::BufrContent(h, true); message::Message msg(c); // verify the presence of section 2 (to store the MARS key) long localSectionPresent = msg.getLong("localSectionPresent"); ok = localSectionPresent != 0; if (!ok) { missingKey++; } else { eckit::OrderedStringDict transformation; switch (checkMessageLength(msg, numMessage, transformation)) { case Status::CORRUPTED: ok = false; messageLength++; break; case Status::FIXED: messageLength++; break; case Status::OK: break; }; switch (checkSubType(msg, numMessage)) { case Status::CORRUPTED: if (!ignoreType_) { ok = false; } inconsistentSubType++; break; case Status::FIXED: inconsistentSubType++; break; case Status::OK: break; }; switch (checkDate(msg, numMessage, transformation)) { case Status::CORRUPTED: ok = false; inconsistentDate++; break; case Status::FIXED: inconsistentDate++; break; case Status::OK: break; }; if (ok) { if (transformation.size() != 0) { msg.transform(transformation); } msg.write(out); } } if (!ok && abort_) { Log::error() << "message " << numMessage << " not compliant" << std::endl; exit(1); } numMessage++; } } catch (eckit::Exception& e) { Log::warning() << " Error parsing message " << numMessage << " - offset " << pos << std::endl; if (verbose_) { e.dumpStackTrace(Log::warning()); } } } while (pos != reader.position()); if (missingKey) Log::warning() << missingKey << " message" << (missingKey > 1 ? "s miss " : " misses ") << " the MARS key" << std::endl; if (messageLength) Log::warning() << messageLength << " message" << (messageLength > 1 ? "s " : " ") << " with incoherent message length in the MARS key" << std::endl; if (inconsistentSubType) Log::warning() << inconsistentSubType << " message" << (inconsistentSubType > 1 ? "s " : " ") << " with unknown or inconsistent subtype" << std::endl; if (inconsistentDate) Log::warning() << inconsistentDate << " message" << (inconsistentDate > 1 ? "s " : " ") << " with inconsistent date" << std::endl; } //---------------------------------------------------------------------------------------------------------------------- int main(int argc, char** argv) { BufrCheck tool(argc, argv); return tool.start(); } metkit-1.16.0/src/tools/compare-mars-requests.py000077500000000000000000000217611513171467200216550ustar00rootroot00000000000000#!/usr/bin/env python3 # (C) Copyright 1996- ECMWF. # This software is licensed under the terms of the Apache Licence Version 2.0 # which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. # In applying this licence, ECMWF does not waive the privileges and immunities # granted to it by virtue of its status as an intergovernmental organisation nor # does it submit to any jurisdiction. # Emanuele Danovaro - ECMWF May 2021 import sys import os.path import json import datetime from dateutil.parser import parse def check_one(name, old, new): assert len(old) == 1 and len(new) == 1, f"{name.upper()}: too many values {len(old)} and {len(new)}" return old[0], new[0] def check_atMostOne(name, old, new): assert len(old) < 2 and len(new) < 2, f"{name.upper()}: too many values {len(old)} and {len(new)}" return old[0] if 0 < len(old) else None, new[0] if 0 < len(new) else None def compare_int(name, old, new): for o, n in zip(old, new): assert str(o).isnumeric() and str(n).isnumeric() and int(o) == int(n), f"{name.upper()}: value mismatch '{old}' and '{new}'" def compare_float(name, old, new): for o, n in zip(old, new): try: o = float(o) except ValueError: o = o.lower() try: n = float(n) except ValueError: n = n.lower() assert o == n, f"{name.upper()}: value mismatch '{old}' and '{new}'" def compare_intAndKeywords(name, old, new, keywords): o, n = check_atMostOne(name, old, new) if o in keywords or str(o).lower() in keywords: o = str(o).lower() if isinstance(o, str) else None if n in keywords or str(n).lower() in keywords: n = str(n).lower() if isinstance(n, str) else None assert o == n or (str(o).isnumeric() and str(n).isnumeric() and int(o) == int(n)), f"{name.upper()}: value mismatch '{old}' and '{new}'" def compare_grid(name, old, new): for o, n in zip(old, new): try: o = float(o) except ValueError: o = o.lower() try: n = float(n) except ValueError: n = n.lower() assert o == n, f"{name.upper()}: value mismatch '{old}' and '{new}'" def compare_expect(name, old, new): # 'any' or a positive integer value compare_intAndKeywords(name, old, new, ["any"]) def compare_accuracy(name, old, new): # 'off', 'av' or a positive integer value compare_intAndKeywords(name, old, new, [None, "off", "av", "n"]) def compare_frame(name, old, new): # 'off' or a positive integer value compare_intAndKeywords(name, old, new, ["off"]) def compare_truncation(name, old, new): # 'none', 'auto', 'off' or a positive integer value compare_intAndKeywords(name, old, new, ["off", "none", "auto"]) def compare_step(name, old, new): for o, n in zip(old, new): oParts = str(o).split('-') nParts = str(n).split('-') assert len(oParts) == len(nParts) and all(float(oi) == float(ni) for oi, ni in zip(oParts, nParts)), f"{name.upper()}: value mismatch '{old}' and '{new}'" def compare_str(name, old, new): o, n = check_one(name, old, new) assert o.replace('"', '').lower() == n.replace('"', '').lower(), f"{name.upper()}: string mismatch '{old[0]}' and '{new[0]}'" def compare_strList(name, old, new): for o, n in zip(old, new): compare_str(name, [o], [n]) def compare_strCaseSensitive(name, old, new): for o, n in zip(old, new): assert o.replace('"', '') == n.replace('"', ''), f"{name.upper()}: string mismatch '{old}' and '{new}'" def compare_time(name, old, new): o, n = check_one(name, old, new) if isinstance(o, str): o = int(o.replace(':', '')) if o>9999: o = o/100 if isinstance(n, str): n = int(n.replace(':', '')) if n > 9999: n = n / 100 assert o == n, f"{name.upper()}: time mismatch '{old[0]}' and '{new[0]}'" def compare_date(name, old, new): o, n = check_one(name, old, new) oStart = parse(str(o), default=datetime.datetime(1901, 1, 1)) oEnd = parse(str(o), default=datetime.datetime(2001, 12, 31)) nStart = parse(str(n), default=datetime.datetime(1901, 1, 1)) nEnd = parse(str(n), default=datetime.datetime(2001, 12, 31)) assert oStart.date() == nStart.date() and oEnd.date() == nEnd.date(), f"{name.upper()}: date mismatch '{old[0]}' and '{new[0]}'" def compare_dates(name, old, new): for o, n in zip(old, new): oStart = parse(str(o), default=datetime.datetime(1901, 1, 1)) oEnd = parse(str(o), default=datetime.datetime(2001, 12, 31)) nStart = parse(str(n), default=datetime.datetime(1901, 1, 1)) nEnd = parse(str(n), default=datetime.datetime(2001, 12, 31)) assert oStart.date() == nStart.date() and oEnd.date() == nEnd.date(), f"{name.upper()}: date mismatch '{o}' and '{n}'" def compare_expver(name, old, new): o, n = check_one(name, old, new) if isinstance(o, str): try: o = int(o) except ValueError: o = o.lower() if isinstance(n, str): try: n = int(n) except ValueError: n = n.lower() assert o == n, f"{name.upper()}: mismatch '{old[0]}' and '{new[0]}'" def ignore(name, old, new): pass def ignore_fixYaml(name, old, new): pass comparators = { "accuracy": ignore_fixYaml, # ????? # "accuracy": compare_accuracy, "anoffset": compare_int, # ????? "area": ignore_fixYaml, "bitmap": compare_strCaseSensitive, # block # channel "class": compare_str, "database": compare_str, # ????? "date": compare_date, "diagnostic": compare_int, # ?????? "direction": compare_int, # should we handle case "all" "domain": compare_str, "duplicates": compare_str, # can we ignore ? "expect": compare_expect, "expver": compare_expver, "fcmonth": compare_int, "fcperiod": compare_step, # ?????? "fieldset": compare_strCaseSensitive, "filter": compare_str, "format": compare_str, # ????? "frame": compare_frame, "frequency": compare_int, # ?????? "grid": compare_grid, "hdate": compare_dates, "ident": compare_int, "interpolation": compare_str, # "intgrid": "iteration": compare_int, # ?????? "latitude": compare_float, "levelist": compare_float, "levtype": compare_str, "longitude": compare_float, "lsm": compare_str, # ????? "method": compare_int, "number": compare_int, "obsgroup": compare_str, # ????? "obstype": compare_int, "origin": compare_expver, # ????? "packing": compare_str, "padding": compare_int, # ?????? "param": compare_float, # <-- to check that short names have been replaced, otherwise we can use compare_strList "priority": compare_int, "product": compare_str, # ????? "range": compare_int, "refdate": compare_date, "reference": compare_int, "reportype": compare_int, "repres": ignore, # resol "rotation": compare_grid, "section": compare_str, "source": compare_strCaseSensitive, "step": compare_step, "stream": compare_str, "system": compare_int, "target": compare_strCaseSensitive, "time": compare_time, "truncation": compare_truncation, "type": compare_str, "use": compare_str } def compare(name, old, new): if not isinstance(old, list): old = [old] if not isinstance(new, list): new = [new] assert len(old) == len(new), f"{name}: list mismatch {len(old)} and {len(new)}" assert name in comparators.keys(), f"{name}: not supported" comparators[name](name, old, new) # compare_date('date', '20210501', '2021-05-01') # compare_date('date', '20210501', '2021-May-01') # compare_date('date', '20210501', '2021-may-01') # compare_date('date', 'May-1', 'may-01') # compare_date('date', 'May', 'may') # compare_date('date', 'May', '20210521') # check command line parameters if len(sys.argv) != 3 or not os.path.isfile(sys.argv[1]) or not os.path.isfile(sys.argv[2]): print('Please specify the json files to be compared.') print('Usage: ',sys.argv[0], ' ') if len(sys.argv)>1 and not os.path.isfile(sys.argv[1]): print(sys.argv[1], 'is not a file') if len(sys.argv)>2 and not os.path.isfile(sys.argv[2]): print(sys.argv[2], 'is not a file') exit(1) #open json files and build case insensitive dictionaries json_lines_1 = [] with open(sys.argv[1]) as json_file: for line in json_file: j = {} for key, value in json.loads(line).items(): j[key.lower()] = value json_lines_1.append(j) json_lines_2 = [] with open(sys.argv[2]) as json_file: for line in json_file: j = {} for key, value in json.loads(line).items(): j[key.lower()] = value json_lines_2.append(j) assert len(json_lines_1) == len(json_lines_2), f"Json mismatch: {sys.argv[1]} contains {len(json_lines_1)} while {sys.argv[2]} contains {len(json_lines_2)}" for j1, j2 in zip(json_lines_1, json_lines_2): for key in set(j1.keys()) | set(j2.keys()): compare(key, j1.get(key), j2.get(key)) metkit-1.16.0/src/tools/grib-blob.cc000066400000000000000000000044271513171467200172070ustar00rootroot00000000000000/* * (C) Copyright 1996- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ #include "eckit/config/Resource.h" #include "eckit/io/Buffer.h" #include "eckit/option/CmdArgs.h" #include "eckit/option/Option.h" #include "eckit/runtime/Tool.h" #include "metkit/codes/GribMetaData.h" using namespace metkit; //---------------------------------------------------------------------------------------------------------------------- class GribBlob; static GribBlob* instance_ = 0; class GribBlob : public eckit::Tool { public: virtual void usage(const std::string& tool) const { eckit::Log::info() << std::endl << "Usage: " << tool << " [path2] ..." << std::endl; } virtual int numberOfPositionalArguments() const { return -1; } virtual int minimumPositionalArguments() const { return 1; } virtual void run(); GribBlob(int argc, char** argv) : eckit::Tool(argc, argv) { ASSERT(instance_ == 0); instance_ = this; } protected: // members std::vector options_; }; static void usage(const std::string& tool) { ASSERT(instance_); instance_->usage(tool); } void GribBlob::run() { eckit::option::CmdArgs args(&::usage, options_, numberOfPositionalArguments(), minimumPositionalArguments()); eckit::Buffer buffer(grib::MetFile::gribBufferSize()); long len = 0; for (size_t i = 0; i < args.count(); i++) { eckit::PathName path(args(i)); std::cout << "Processing " << path << std::endl; grib::MetFile file(path); size_t nMsg = 0; while ((len = file.readSome(buffer)) != 0) { metkit::grib::GribMetaData grib(buffer, len); ++nMsg; eckit::Log::info() << nMsg << " " << grib << std::endl; } } } //---------------------------------------------------------------------------------------------------------------------- int main(int argc, char** argv) { GribBlob tool(argc, argv); return tool.start(); } metkit-1.16.0/src/tools/mars-archive-script.cc000066400000000000000000000216351513171467200212330ustar00rootroot00000000000000 #include "eckit/io/DataHandle.h" #include "eckit/io/FileHandle.h" #include "eckit/option/CmdArgs.h" #include "eckit/option/SimpleOption.h" #include "metkit/mars/MarsParser.h" #include "metkit/tool/MetkitTool.h" #include using namespace metkit; using namespace metkit::mars; using namespace eckit; using namespace eckit::option; //---------------------------------------------------------------------------------------------------------------------- class MarsArchiveScript : public MetkitTool { using OverridesDict = std::map>>; public: // methods MarsArchiveScript(int argc, char** argv); ~MarsArchiveScript() override = default; private: // methods void init(const CmdArgs& args) override; void execute(const CmdArgs& args) override; void usage(const std::string& tool) const override; OverridesDict extractOverrides(MarsRequest& request); template void setOverrides(MarsRequest& rq, const OverridesDict& overrides, const char* overrideName, Args... more); void setOverrides(MarsRequest& rq, const OverridesDict& overrides); std::string srcfile(int cnt) const; std::string arcfile(int cnt) const; std::string cmpfile(int cnt) const; private: // members std::string infile_; std::string outfile_; std::string tempPrefix_; bool obs_; bool compare_; // Output environment variables std::string preObs_; std::string retrieveMars_; std::string archiveMars_; std::string compareMars_; std::string unblockCommand_; std::string retrieveComplete_; std::string archiveComplete_; std::string compareComplete_; std::string compareCommand_; }; //---------------------------------------------------------------------------------------------------------------------- MarsArchiveScript::MarsArchiveScript(int argc, char** argv) : MetkitTool(argc, argv), tempPrefix_("mars"), obs_(false), compare_(false), preObs_("PREOBS"), retrieveMars_("RETRIEVE_MARS"), archiveMars_("ARCHIVE_MARS"), compareMars_("COMPARE_MARS"), unblockCommand_("UNBLOCK"), retrieveComplete_("RETRIEVE_COMPLETE"), archiveComplete_("ARCHIVE_COMPLETE"), compareComplete_("COMPARE_COMPLETE"), compareCommand_("COMPARE") { options_.push_back(new SimpleOption("out", "Output filename (defaults output to stdout)")); options_.push_back(new SimpleOption("in", "Input filename (defaults input to stdin)")); options_.push_back(new SimpleOption("obs", "Handle observations rather than output GRIBs")); options_.push_back(new SimpleOption("compare", "Re-retrieve and compare results")); options_.push_back( new SimpleOption("legacy", "Use legacy environment variable names for old suite compatability")); options_.push_back(new SimpleOption("prefix", "Prefix for the temporary files. Typically \"mars\"")); } void MarsArchiveScript::usage(const std::string& tool) const { Log::info() << "Usage: " << tool << " [options]" << eckit::newl << eckit::newl << "Note: The output of this tool assumes that we are running in an ecflow suite with" << eckit::newl << " failure trapping enabled, as well as the following environment variables:" << eckit::newl << " RETRIEVE_MARS, ARCHIVE_MARS, COMPARE_MARS, UNBLOCK, RETRIEVE_COMPLETE" << eckit::newl << " ARCHIVE_COMPLETE, COMPARE_COMPLETE" << eckit::newl << eckit::newl << "Examples:" << eckit::newl << "=========" << eckit::newl << std::endl; } void MarsArchiveScript::init(const CmdArgs& args) { infile_ = args.getString("in", infile_); outfile_ = args.getString("out", outfile_); compare_ = args.getBool("compare", compare_); tempPrefix_ = args.getString("prefix", tempPrefix_); obs_ = args.getBool("obs", obs_); if (args.getBool("legacy", false)) { retrieveMars_ = "MARS_FROM_FDB"; archiveMars_ = "MARS_TO_IBM"; compareMars_ = "MARS_FROM_IBM"; unblockCommand_ = "UNBLOCK"; retrieveComplete_ = "FDB_COMPLETE"; archiveComplete_ = "ARC_COMPLETE"; compareComplete_ = "CMP_COMPLETE"; } if (obs_) compareCommand_ = "COMPOBS"; } std::string MarsArchiveScript::srcfile(int cnt) const { return tempPrefix_ + ".source." + translate(cnt); } std::string MarsArchiveScript::arcfile(int cnt) const { return tempPrefix_ + ".archive." + translate(cnt); } std::string MarsArchiveScript::cmpfile(int cnt) const { return tempPrefix_ + ".compare." + translate(cnt); } MarsArchiveScript::OverridesDict MarsArchiveScript::extractOverrides(MarsRequest& request) { OverridesDict ret; std::vector keys; request.getParams(keys); for (const auto& k : keys) { int pos = k.find('@'); if (pos != std::string::npos) { std::vector vals; request.getValues(k, vals); ret[k.substr(0, pos)][k.substr(pos + 1)] = vals; request.erase(k); } } return ret; } template void MarsArchiveScript::setOverrides(MarsRequest& rq, const OverridesDict& overrides, const char* overrideName, Args... more) { auto namedset = overrides.find(overrideName); if (namedset != overrides.end()) { for (const auto& kv : namedset->second) { rq.setValue(kv.first, kv.second); } } setOverrides(rq, overrides, more...); } void MarsArchiveScript::setOverrides(MarsRequest& rq, const OverridesDict& overrides) {} void MarsArchiveScript::execute(const CmdArgs& args) { // Input from file, or from stdin? std::unique_ptr in_file; if (!infile_.empty()) { in_file = std::make_unique(infile_.c_str(), std::ios::in | std::ios::binary); in_file->exceptions(std::ios::badbit); } std::istream& in(in_file ? *in_file : std::cin); // Output to file, or to stdout? std::unique_ptr out_file; if (!outfile_.empty()) { out_file = std::make_unique(outfile_.c_str(), std::ios::out | std::ios::binary); out_file->exceptions(std::ios::badbit); } std::ostream& out(out_file ? *out_file : std::cout); // Parse the input request MarsParser parser(in); auto requests = parser.parse(); std::vector overrides; for (auto& rq : requests) { overrides.emplace_back(extractOverrides(rq)); } // 1. Retrieve the source data (typically from the FDB) // n.b. loop over non-const, non-reference requests --> mutable copy in the loops int cnt = 0; if (obs_) { for (cnt = 0; cnt < requests.size(); ++cnt) { out << "$" << preObs_ << " $header." << translate(cnt + 1) << " $data." << translate(cnt + 1) << " " << arcfile(cnt) << "\n\n"; } } else { out << "$" << retrieveMars_ << " << @\n\n"; cnt = 0; for (auto rq : requests) { rq.verb("retrieve"); rq.setValue("target", srcfile(cnt)); setOverrides(rq, overrides[cnt++], "default", "retrieve", "fdb_retrieve"); rq.dump(out); } out << "@\n\n$" << retrieveComplete_ << "\n\n"; // 1.a) Any intermediate step required. Typically ln -s (historically handle "blocked" data output by older // Fortran // based systems) for (cnt = 0; cnt < requests.size(); ++cnt) { out << "$" << unblockCommand_ << " " << srcfile(cnt) << " " << arcfile(cnt) << "\n\n"; } } // 2. Archive the data out << "$" << archiveMars_ << " << @\n\n"; cnt = 0; for (auto rq : requests) { rq.verb("archive"); rq.setValue("source", arcfile(cnt)); setOverrides(rq, overrides[cnt++], "default", "archive"); rq.dump(out); } out << "@\n\n$" << archiveComplete_; // 3. Comparison of re-retrieved data if (compare_) { out << "\n\n$" << compareMars_ << " << @\n\n"; cnt = 0; for (MarsParsedRequest rq : requests) { rq.verb("retrieve"); rq.setValue("target", cmpfile(cnt)); setOverrides(rq, overrides[cnt++], "default", "compare", "ibm_retrieve"); rq.dump(out); } out << "@\n\n"; for (cnt = 0; cnt < requests.size(); ++cnt) { out << "$" << compareCommand_ << " " << arcfile(cnt) << " " << cmpfile(cnt) << "\n\n"; } out << "$" << compareComplete_; } out << std::endl; } //---------------------------------------------------------------------------------------------------------------------- int main(int argc, char** argv) { MarsArchiveScript tool(argc, argv); return tool.start(); }metkit-1.16.0/src/tools/message-to-mars.cc000066400000000000000000000035631513171467200203540ustar00rootroot00000000000000/* * (C) Copyright 1996- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ #include "eckit/config/Resource.h" #include "eckit/io/Buffer.h" #include "eckit/io/Offset.h" #include "eckit/runtime/Tool.h" #include "metkit/codes/GribToRequest.h" #include "metkit/mars/MarsRequest.h" using namespace metkit; using metkit::grib::MetFile; //---------------------------------------------------------------------------------------------------------------------- class Grib2Request : public eckit::Tool { public: Grib2Request(int argc, char** argv) : Tool(argc, argv) { path_ = eckit::Resource("-in", "input.grib"); ///< @todo Move to use Option } virtual ~Grib2Request() {} virtual void run(); private: // members eckit::PathName path_; }; void Grib2Request::run() { eckit::Log::debug() << "Opening GRIB file : " << path_ << std::endl; eckit::Buffer buffer(MetFile::gribBufferSize()); long len = 0; grib::MetFile file(path_); metkit::mars::MarsRequest onereq("GRIB"); size_t nMsg = 0; while ((len = file.readSome(buffer)) != 0) { metkit::mars::MarsRequest req("GRIB"); grib::GribToRequest::gribToRequest(buffer, len, req); // eckit::Log::info() << req << std::endl; ++nMsg; onereq.merge(req); } eckit::Log::info() << onereq << std::endl; } //---------------------------------------------------------------------------------------------------------------------- int main(int argc, char** argv) { Grib2Request tool(argc, argv); return tool.start(); } metkit-1.16.0/src/tools/nccompare.py000077500000000000000000000074731513171467200173710ustar00rootroot00000000000000#!/usr/bin/env python # (C) Copyright 1996- ECMWF. # This software is licensed under the terms of the Apache Licence Version 2.0 # which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. # In applying this licence, ECMWF does not waive the privileges and immunities # granted to it by virtue of its status as an intergovernmental organisation nor # does it submit to any jurisdiction. # Baudouin Raoult - ECMWF Jan 2015 # See http://unidata.github.io/netcdf4-python/netCDF4.Dataset-class.html from netCDF4 import Dataset import sys import numpy ERRORS = 0 def error(text): global ERRORS ERRORS += 1 print "+ ERROR:", text def mismatch(title, v1, v2): global ERRORS ERRORS += 1 print "+ MISMATCH:", title print " FILE:", sys.argv[1] print " VALUE:", v1 print " FILE:", sys.argv[2] print " VALUE:", v2 def compare_lists(what, l1, l2): s1 = set(l1) s2 = set(l2) if len(s1 - s2): error("%s [%s] only in %s" % (what, ",".join([str(x) for x in list(s1-s2)]), sys.argv[1])) return False if len(s2 - s1): error("%s [%s] only in %s" % (what, ",".join([str(x) for x in list(s2-s1)]), sys.argv[2])) return False return True def compare_attributes(ns, name, a1, a2): if type(a1) != type(a2): mismatch("Type of attributes '%s:%s'" % (ns, name,), type(a1), type(a2)) if a1 != a2: a1 = str(a1) a2 = str(a2) if len(a1) > 80: a1 = a1[:79] + '...' if len(a2) > 80: a2 = a2[:79] + '...' mismatch("Value of attributes '%s:%s'" % (ns, name,), a1, a2) def compare_variables(name, v1, v2): compare_lists("Dimensions for '%s'" % (name,), v1.dimensions, v2.dimensions) if v1.datatype != v2.datatype: mismatch("Type of variable '%s'" % (name,), v1.datatype, v2.datatype) if compare_lists("Variable '%s' attributes" % (name,), v1.ncattrs(), v2.ncattrs()): for a in v1.ncattrs(): compare_attributes(name, a, v1.getncattr(a), v2.getncattr(a)) vals1 = v1[:] vals2 = v2[:] if vals1.size != vals2.size: mismatch("Size of variable '%s'" % (name,), vals1.size, vals2.size) if not (vals1 == vals2).all(): vals1 = vals1.flatten() vals2 = vals2.flatten() idx = numpy.nonzero(vals1 - vals2)[0][0] if idx < len(vals1) and idx < len(vals2): mismatch("Value for variable '%s', first difference at index %s" % (name, idx), vals1[idx], vals2[idx]) def compare_dimensions(name, d1, d2): if len(d1) != len(d2): mismatch("Length of dimension '%s'" % (name,), len(d1), len(d2)) def check_file(nc, path): if len(nc.groups): error("Groups not supported (file %s)" % (path,)) if len(nc.cmptypes): error("Compound types not supported (file %s)" % (path,)) if len(nc.vltypes): error("Variable-length types not supported (file %s)" % (path,)) def compare_files(nc1, nc2): check_file(nc1, sys.argv[1]) check_file(nc2, sys.argv[2]) dims1 = nc1.dimensions dims2 = nc2.dimensions if compare_lists("Dimensions", dims1.keys(), dims2.keys()): for k in dims2.keys(): compare_dimensions(k, dims1[k], dims2[k]) vars1 = nc1.variables vars2 = nc2.variables if compare_lists("Variables", vars1.keys(), vars2.keys()): for k in vars1.keys(): compare_variables(k, vars1[k], vars2[k]) if compare_lists("Global attributes", nc1.ncattrs(), nc2.ncattrs()): for a in nc1.ncattrs(): compare_attributes("", a, nc1.getncattr(a), nc2.getncattr(a)) # Other things to checks # print nc1.data_model, nc1.disk_format # print nc1.parent, nc1.vltypes nc1 = Dataset(sys.argv[1], 'r') nc2 = Dataset(sys.argv[2], 'r') compare_files(nc1, nc2) if ERRORS: sys.exit(1) metkit-1.16.0/src/tools/ncmerge.cc000066400000000000000000000020311513171467200167550ustar00rootroot00000000000000/* * (C) Copyright 1996- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ // Baudouin Raoult - ECMWF Jan 2015 #include "metkit/netcdf/InputDataset.h" #include "metkit/netcdf/NCFileCache.h" #include "metkit/netcdf/OutputDataset.h" #include using namespace metkit::netcdf; int main(int argc, char** argv) { try { NCFileCache cache; OutputDataset out("out.nc", cache); for (int i = 1; i < argc; i++) { InputDataset f(argv[i], cache); std::cout << "@@@@@@@@@@@ " << argv[i] << std::endl; out.merge(f); } out.save(); } catch (std::exception& e) { std::cerr << e.what() << std::endl; return 1; } return 0; } metkit-1.16.0/src/tools/odb-to-request.cc000066400000000000000000000115001513171467200202100ustar00rootroot00000000000000/* * (C) Copyright 1996- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ #include #include #include #include "eckit/filesystem/PathName.h" #include "eckit/io/FileHandle.h" #include "eckit/log/JSON.h" #include "eckit/log/Log.h" #include "eckit/option/CmdArgs.h" #include "eckit/option/Option.h" #include "eckit/option/SimpleOption.h" #include "eckit/runtime/Tool.h" #include "eckit/utils/StringTools.h" #include "metkit/odb/OdbToRequest.h" #include "metkit/tool/MetkitTool.h" using namespace metkit; using namespace eckit; using namespace eckit::option; //---------------------------------------------------------------------------------------------------------------------- class OdbToRequestTool : public MetkitTool { public: OdbToRequestTool(int argc, char** argv) : MetkitTool(argc, argv) { options_.push_back(new SimpleOption("verb", "Verb in the request, default = retrieve")); options_.push_back( new SimpleOption("database", "add database keyword to requests, default = none")); options_.push_back(new SimpleOption("source", "add source keyword to requests, default = none")); options_.push_back(new SimpleOption("target", "add target keyword to requests, default = none")); options_.push_back(new SimpleOption("one", "Merge into only one request, default = false")); options_.push_back(new SimpleOption("constant", "Only constant columns, default = true")); options_.push_back(new SimpleOption("json", "Format request in json, default = false")); } virtual ~OdbToRequestTool() {} private: // methods int minimumPositionalArguments() const { return 1; } virtual void execute(const eckit::option::CmdArgs& args); virtual void init(const CmdArgs& args); virtual void usage(const std::string& tool) const; private: // members std::vector paths_; std::string verb_ = "retrieve"; std::string database_ = ""; std::string source_ = ""; std::string target_ = ""; bool one_ = false; bool constant_ = true; bool json_ = false; }; //---------------------------------------------------------------------------------------------------------------------- void OdbToRequestTool::init(const CmdArgs& args) { args.get("one", one_); args.get("constant", constant_); args.get("verb", verb_); args.get("database", database_); args.get("source", source_); args.get("target", target_); args.get("json", json_); if (json_) { porcelain_ = true; } } void OdbToRequestTool::usage(const std::string& tool) const { Log::info() << "Usage: " << tool << " [options] [request1] [request2] ..." << std::endl << std::endl; Log::info() << "Examples:" << std::endl << "=========" << std::endl << std::endl << tool << " --one --verb=retrieve data.odb" << std::endl << std::endl; } static void toJSON(const std::vector& requests) { JSON j(Log::info()); for (auto& r : requests) { r.json(j); } Log::info() << std::endl; } static void toStdOut(const std::vector& requests) { for (auto& r : requests) { eckit::Log::info() << r << std::endl; } } static void addKeyValue(std::vector& requests, const std::string& key, const std::string& value) { std::transform(requests.begin(), requests.end(), requests.begin(), [key, value](MarsRequest& r) -> MarsRequest { r.setValue(key, value); return r; }); } void OdbToRequestTool::execute(const eckit::option::CmdArgs& args) { PathName inFile(args(0)); FileHandle dh(inFile); dh.openForRead(); std::vector requests = odb::OdbToRequest(verb_, one_, constant_).odbToRequest(dh); if (not database_.empty()) addKeyValue(requests, "database", database_); if (StringTools::lower(verb_) == "archive") { addKeyValue(requests, "source", inFile); } if (not source_.empty()) addKeyValue(requests, "source", source_); if (not target_.empty()) addKeyValue(requests, "target", target_); if (json_) { toJSON(requests); } else { toStdOut(requests); } } //---------------------------------------------------------------------------------------------------------------------- int main(int argc, char** argv) { OdbToRequestTool tool(argc, argv); return tool.start(); } metkit-1.16.0/src/tools/parse-mars-request.cc000066400000000000000000000120471513171467200211050ustar00rootroot00000000000000/* * (C) Copyright 1996- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ #include #include #include "eckit/io/Buffer.h" #include "eckit/io/Offset.h" #include "eckit/log/JSON.h" #include "eckit/option/CmdArgs.h" #include "eckit/option/SimpleOption.h" #include "metkit/mars/MarsExpansion.h" #include "metkit/mars/MarsParser.h" #include "metkit/mars/MarsRequest.h" #include "metkit/tool/MetkitTool.h" using namespace metkit; using namespace metkit::mars; using namespace eckit; using namespace eckit::option; //---------------------------------------------------------------------------------------------------------------------- class ParseRequest : public MetkitTool { public: ParseRequest(int argc, char** argv) : MetkitTool(argc, argv) { options_.push_back(new SimpleOption("json", "Format request in json, default = false")); options_.push_back(new SimpleOption("compact", "Compact output, default = false")); } virtual ~ParseRequest() {} private: // methods int minimumPositionalArguments() const { return 1; } void process(const eckit::PathName& path); virtual void execute(const eckit::option::CmdArgs& args); virtual void init(const CmdArgs& args); virtual void usage(const std::string& tool) const; private: // members bool json_ = false; bool compact_ = false; }; //---------------------------------------------------------------------------------------------------------------------- void ParseRequest::execute(const eckit::option::CmdArgs& args) { for (size_t i = 0; i < args.count(); i++) { process(args(i)); } } void ParseRequest::init(const CmdArgs& args) { args.get("json", json_); args.get("compact", compact_); args.get("porcelain", porcelain_); if (porcelain_) compact_ = true; } void ParseRequest::usage(const std::string& tool) const { Log::info() << "Usage: " << tool << " [options] [request1] [request2] ..." << std::endl << std::endl; Log::info() << "Examples:" << std::endl << "=========" << std::endl << std::endl << tool << " --json mars1.req mars2.req" << std::endl << tool << " --porcelain folderOfRequests" << std::endl << std::endl; } void ParseRequest::process(const eckit::PathName& path) { if (path.isDir()) { std::vector files; std::vector directories; path.children(files, directories); std::sort(files.begin(), files.end()); std::sort(directories.begin(), directories.end()); for (std::vector::const_iterator j = files.begin(); j != files.end(); ++j) { process(*j); } for (std::vector::const_iterator j = directories.begin(); j != directories.end(); ++j) { process(*j); } return; } if (!porcelain_) { std::cout << "==========> Parsing : " << path << std::endl; } std::ifstream in(path.asString().c_str()); MarsParser parser(in); bool inherit = true; MarsExpansion expand(inherit); auto p = parser.parse(); if (!porcelain_) { for (auto j = p.begin(); j != p.end(); ++j) { if (compact_) { j->dump(std::cout, "", ""); std::cout << std::endl; } else { j->dump(std::cout); } } std::cout << "----------> Expanding ... " << std::endl; } std::vector v = expand.expand(p); for (std::vector::const_iterator j = v.begin(); j != v.end(); ++j) { if (json_) { if (compact_) { eckit::JSON jsonOut(std::cout); j->json(jsonOut); } else { eckit::JSON jsonOut(std::cout, eckit::JSON::Formatting(eckit::JSON::Formatting::BitFlags::INDENT_DICT)); j->json(jsonOut); } std::cout << std::endl; } else { if (compact_) { j->dump(std::cout, "", ""); std::cout << std::endl; } else { j->dump(std::cout); } } } class Print : public FlattenCallback { virtual void operator()(const MarsRequest& request) { std::cout << request << std::endl; } }; Print cb; // for (std::vector::const_iterator j = v.begin(); j != v.end(); ++j) { // expand.flatten(*j, cb, filter); // } } //---------------------------------------------------------------------------------------------------------------------- int main(int argc, char** argv) { ParseRequest tool(argc, argv); return tool.start(); } metkit-1.16.0/tests/000077500000000000000000000000001513171467200142455ustar00rootroot00000000000000metkit-1.16.0/tests/CMakeLists.txt000066400000000000000000000074511513171467200170140ustar00rootroot00000000000000# (C) Copyright 1996- ECMWF. # # This software is licensed under the terms of the Apache Licence Version 2.0 # which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. # In applying this licence, ECMWF does not waive the privileges and immunities # granted to it by virtue of its status as an intergovernmental organisation # nor does it submit to any jurisdiction. list(APPEND metkit_env "METKIT_HOME=${CMAKE_BINARY_DIR}") if( DEFINED ECCODES_DEFINITION_PATH ) list(APPEND metkit_env "ECCODES_DEFINITION_PATH=${ECCODES_DEFINITION_PATH}") elseif( IS_DIRECTORY "${CMAKE_BINARY_DIR}/share/eccodes/definitions" ) list(APPEND metkit_env "ECCODES_DEFINITION_PATH=${CMAKE_BINARY_DIR}/share/eccodes/definitions") endif() ecbuild_get_test_multidata( TARGET grib_get_data DIRNAME grib-api/test-data/data NAMES latlon.grib synthetic_2msgs.grib ) ecbuild_get_test_multidata( TARGET metkit_get_odb_data NAMES multiodb.odb multiodb2.odb NOCHECK ) add_custom_target(soft_link_expand_test_data ALL COMMAND ${CMAKE_COMMAND} -E create_symlink "${CMAKE_CURRENT_SOURCE_DIR}/expand" "${CMAKE_CURRENT_BINARY_DIR}/expand") ecbuild_add_test( TARGET metkit_test_multihandle CONDITION HAVE_GRIB INCLUDES "${ECCODES_INCLUDE_DIRS}" SOURCES test_multihandle.cc LIBS metkit NO_AS_NEEDED TEST_DEPENDS grib_get_data ENVIRONMENT "${metkit_env}" ) ecbuild_add_test( TARGET "metkit_test_codes_decoder" CONDITION HAVE_GRIB OR HAVE_BUFR SOURCES "test_codes_decoder.cc" INCLUDES "${ECKIT_INCLUDE_DIRS}" "${ECCODES_INCLUDE_DIR}" LIBS metkit NO_AS_NEEDED ENVIRONMENT "${metkit_env}" ) ecbuild_add_test( TARGET metkit_test_odbsplitter CONDITION HAVE_ODB SOURCES test_odbsplitter.cc INCLUDES "${ECKIT_INCLUDE_DIRS}" TEST_DEPENDS metkit_get_odb_data NO_AS_NEEDED LIBS metkit ) ecbuild_add_test( TARGET metkit_test_gribhandle CONDITION HAVE_GRIB SOURCES test_gribhandle.cc INCLUDES "${ECKIT_INCLUDE_DIRS}" "${ECCODES_INCLUDE_DIR}" LIBS metkit TEST_DEPENDS grib_get_data NO_AS_NEEDED ENVIRONMENT "${metkit_env}") foreach( test c_api codes_api context date expand filter hypercube integer_range matcher language mars_language mars_language_strict obstype param_axis request step steprange_axis time type_levelist typesfactory ) ecbuild_add_test( TARGET "metkit_test_${test}" SOURCES "test_${test}.cc" INCLUDES "${ECKIT_INCLUDE_DIRS}" ENVIRONMENT "${metkit_env}" NO_AS_NEEDED LIBS metkit) endforeach() # Compile C test ecbuild_add_test( TARGET metkit_test_c_compiled SOURCES test_c_api.c INCLUDES "${ECKIT_INCLUDE_DIRS}" LIBS metkit NO_AS_NEEDED ENVIRONMENT "${metkit_env}") # if ( HAVE_NETCDF ) # add_subdirectory(netcdf) # endif() add_subdirectory(regressions) add_subdirectory(marsgen) metkit-1.16.0/tests/expand/000077500000000000000000000000001513171467200155245ustar00rootroot00000000000000metkit-1.16.0/tests/expand/MARSC-223.expected000066400000000000000000000010101513171467200204100ustar00rootroot00000000000000 RETRIEVE, CLASS = OD, TYPE = FC, STREAM = OPER, EXPVER = 0001, REPRES = GG, LEVTYPE = SFC, PARAM = 33, DATE = 20231221, TIME = 0000, STEP = 0, DOMAIN = G, TARGET = reference.zcbyW7.data, RESOL = AUTO, GRID = .125/.125, PADDING = 0, USE = INFREQUENT metkit-1.16.0/tests/expand/MARSC-223.req000066400000000000000000000002661513171467200174120ustar00rootroot00000000000000retrieve, date=2023-12-21,expver=1,grid=0.125/0.125,levtype=sfc,padding=0,param=33.128,step=0,stream=oper,time=00:00:00,type=fc,use=infrequent, target="reference.zcbyW7.data"metkit-1.16.0/tests/expand/MARSC-224.expected000066400000000000000000000012671513171467200204270ustar00rootroot00000000000000 RETRIEVE, CLASS = TI, TYPE = FC, STREAM = OPER, EXPVER = prod, REPRES = SH, LEVTYPE = SFC, PARAM = 151, DATE = 20231226, TIME = 1200, STEP = 0/6/12/18/24/30/36/42/48/54/60/66/72/78/84/90/96/102/108/114/120/126/132/138/144/150/156/162/168/174/180/186/192/198/204/210/216/222/228/234/240, NUMBER = ALL, ORIGIN = ECMF, TARGET = reference.OkV8i4.data, RESOL = AUTO, GRID = .5/.5, PADDING = 0, PROCESS = LOCAL metkit-1.16.0/tests/expand/MARSC-224.req000066400000000000000000000002771513171467200174150ustar00rootroot00000000000000retrieve, class=ti,date=20231226/to/20231226,expver=prod,grid=0.5/0.5,levtype=sfc,padding=0,param=151,step=0/to/240/by/6,time=12,type=fc,number=all,origin=ecmf, target="reference.OkV8i4.data"metkit-1.16.0/tests/expand/MARSC-225.expected000066400000000000000000000013741513171467200204270ustar00rootroot00000000000000RETRIEVE, CLASS = TI, TYPE = PF, STREAM = ENFO, EXPVER = prod, REPRES = SH, LEVTYPE = SFC, PARAM = 167, DATE = 20231230, TIME = 0000, STEP = 0/6/12/18/24/30/36/42/48/54/60/66/72/78/84/90/96/102/108/114/120/126/132/138/144/150/156/162/168/174/180/186/192/198/204/210/216/222/228/234/240/246/252/258/264/270/276/282/288/294/300/306/312/318/324/330/336/342/348/354/360, NUMBER = 1, ORIGIN = ECMF, TARGET = reference.8nWO8K.data, RESOL = AUTO, GRID = .2/.2, PADDING = 0, PROCESS = LOCALmetkit-1.16.0/tests/expand/MARSC-225.req000066400000000000000000000002711513171467200174100ustar00rootroot00000000000000retrieve, class=ti,date=2023-12-30,expver=prod,grid=0.2/0.2,levtype=sfc,padding=0,param=167,step=0/to/360/by/6,time=00:00:00,type=pf,number=1,origin=ecmf, target="reference.8nWO8K.data"metkit-1.16.0/tests/expand/MARSC-227.expected000066400000000000000000000010071513171467200204220ustar00rootroot00000000000000RETRIEVE, CLASS = OD, TYPE = FC, STREAM = OPER, EXPVER = 0001, REPRES = GG, LEVTYPE = SFC, PARAM = 33, DATE = 20231221, TIME = 0000, STEP = 0, DOMAIN = G, TARGET = reference.zcbyW7.data, RESOL = AUTO, GRID = .125/.125, PADDING = 0, USE = INFREQUENT metkit-1.16.0/tests/expand/MARSC-227.req000066400000000000000000000002561513171467200174150ustar00rootroot00000000000000retrieve, date=2023-12-21,expver=1,grid=0.125/0.125,levtype=sfc,padding=0,param=33.128,step=0,stream=oper,time=00:00:00,type=fc,use=infrequent, target="reference.zcbyW7.data"metkit-1.16.0/tests/expand/MARSC-228.expected000066400000000000000000000005271513171467200204310ustar00rootroot00000000000000RETRIEVE,     CLASS      = OD,     TYPE       = OB,     STREAM     = OPER,     EXPVER     = 0001,     REPRES     = BU,     OBSTYPE    = 1,     DATE       = 20210501,     TIME       = 2101,     DOMAIN     = G,     TARGET     = reference.xoB8Cx.data,     DUPLICATES = KEEP,     RANGE      = 179metkit-1.16.0/tests/expand/MARSC-228.re000066400000000000000000000002201513171467200172240ustar00rootroot00000000000000retrieve, date=20210501,time=2101/to/2400,type=ob,target="/ec/fws2/sb/work/rd/erds/i7ug/LWDA/2021050200/an/scat", target="reference.xoB8Cx.data"metkit-1.16.0/tests/expand/MARSC-231.expected000066400000000000000000000005671513171467200204270ustar00rootroot00000000000000RETRIEVE, CLASS = OD, TYPE = FC, STREAM = OPER, EXPVER = 0001, REPRES = GG, LEVTYPE = SFC, PARAM = 167, DATE = 20231231, TIME = 0000/1200, STEP = 0, DOMAIN = G, TARGET = reference.vEDx0X.data, RESOL = AUTO, AREA = 58/-10/35/80, GRID = .1/.1 metkit-1.16.0/tests/expand/MARSC-231.req000066400000000000000000000003601513171467200174040ustar00rootroot00000000000000retrieve, area=58./-10./35./80,class=od,date=20231231,expver=1,grid=0.1/0.1,levtype=surf,param=2t,step=0,stream=oper,time=00:00:00/12:00:00,type=fc,target=target.bbafa703-e7da-4383-8c34-d36a7cbee4f5,repres=gg, target="reference.vEDx0X.data"metkit-1.16.0/tests/expand/MARSC-232.expected000066400000000000000000000006711513171467200204240ustar00rootroot00000000000000RETRIEVE, DATASET = mars, CLASS = OD, TYPE = FC, STREAM = OPER, EXPVER = 0001, REPRES = GG, LEVTYPE = SFC, PARAM = 144, DATE = 20231003, TIME = 0000/1200, STEP = 0/1/2/3/4/5/6/7/8/9/10/11/12, DOMAIN = G, TARGET = reference.data, RESOL = AUTO, AREA = 85/-180/-60/180, GRID = .1/.1, PADDING = 0 metkit-1.16.0/tests/expand/MARSC-232.req000066400000000000000000000003551513171467200174110ustar00rootroot00000000000000retrieve, area=85.000/-180.000/-60.000/180.000,class=od,date=20231003/to/20231003,expver=1,grid=0.100/0.100,levtype=sfc,padding=0,param=144.128,step=0/to/12/by/1,stream=oper,time=00/12,type=fc,dataset=mars, target=reference.data metkit-1.16.0/tests/expand/MARSC-233 copy.expected000066400000000000000000000007001513171467200213510ustar00rootroot00000000000000RETRIEVE, DATASET = tigge, CLASS = TI, TYPE = FC, STREAM = OPER, EXPVER = prod, REPRES = SH, LEVTYPE = PL, LEVELIST = 250/500/850, PARAM = 156, DATE = 20231224, TIME = 0000/1200, STEP = 0, ORIGIN = RKSL, TARGET = reference.data, RESOL = AUTO, AREA = 90/0/-90/359.75, GRID = .25/.25, PADDING = 0metkit-1.16.0/tests/expand/MARSC-233.expected000066400000000000000000000007311513171467200204220ustar00rootroot00000000000000RETRIEVE, DATASET = tigge, CLASS = TI, TYPE = FC, STREAM = OPER, EXPVER = prod, REPRES = SH, LEVTYPE = PL, LEVELIST = 250/500/850, PARAM = 156, DATE = 20231224, TIME = 0000/1200, STEP = 0, ORIGIN = RKSL, TARGET = reference.data, RESOL = AUTO, AREA = 90/0/-90/359.75, GRID = .25/.25, PADDING = 0, PROCESS = LOCAL metkit-1.16.0/tests/expand/MARSC-233.req000066400000000000000000000003351513171467200174100ustar00rootroot00000000000000retrieve,area=90.0/0.0/-90.0/359.75,class=ti,date=20231224,expver=prod,grid=0.25/0.25,levtype=pl,padding=0,param=156,step=0,time=0000/1200,type=fc,levelist=250/500/850,origin=rksl,dataset=tigge, target=reference.data metkit-1.16.0/tests/expand/MARSC-234.expected000066400000000000000000000005731513171467200204270ustar00rootroot00000000000000RETRIEVE, CLASS = OD, TYPE = FC, STREAM = OPER, EXPVER = 0001, REPRES = GG, LEVTYPE = SFC, PARAM = 228022, DATE = 20231220, TIME = 1200, STEP = 0, DOMAIN = G, TARGET = reference.A0FgVE.data, RESOL = AUTO, AREA = 73.5/-27/33/45, GRID = .125/.125 metkit-1.16.0/tests/expand/MARSC-234.req000066400000000000000000000003351513171467200174110ustar00rootroot00000000000000retrieve, area=Europe,class=od,date=2023-12-20,expver=1,grid=0.125/0.125,levtype=sfc,param=22.228,step=0,stream=oper,time=12:00:00,type=fc,target=target.27f72f51-1e60-437f-b1ce-e57129e2dff6, target="reference.A0FgVE.data"metkit-1.16.0/tests/expand/MARSC-236.expected000066400000000000000000000007141513171467200204260ustar00rootroot00000000000000RETRIEVE, CLASS = OD, TYPE = AN, STREAM = OPER, EXPVER = 0001, REPRES = GG, LEVTYPE = SFC, PARAM = 134/137/165/166/167/168/235, DATE = 20240102, TIME = 0000, STEP = 0, DOMAIN = G, TARGET = data.reference, RESOL = AV, ACCURACY = 12, STYLE = DISSEMINATION, AREA = 90/0/-90/359.5, GRID = .5/.5, PADDING = 0 metkit-1.16.0/tests/expand/MARSC-236.req000066400000000000000000000003331513171467200174110ustar00rootroot00000000000000retrieve, accuracy=12,area=90.0/0.0/-90.0/359.5,date=20240102,domain=g,grid=0.5/0.5,leve=off,levtype=sfc,padding=0,param=134/137/165/166/167/168/235,stream=da,style=dissemination,time=00,type=an, target="data.reference"metkit-1.16.0/tests/expand/MARSC-237.expected000066400000000000000000000010071513171467200204230ustar00rootroot00000000000000RETRIEVE, CLASS = OD, TYPE = FC, STREAM = OPER, EXPVER = 0001, REPRES = GG, LEVTYPE = SFC, PARAM = 151, DATE = 20240101, TIME = 0000, STEP = 0/3/6/9/12/15/18/21/24/27/30/33/36/39/42/45/48/51/54/57/60/63/66/69/72/75/78/81/84/87/90/93/96/99/102/105/108/111/114/117/120, DOMAIN = G, TARGET = reference.Hx2aUM.data, RESOL = AUTO, AREA = 90/-180/-90/180, GRID = .25/.25, PADDING = 0 metkit-1.16.0/tests/expand/MARSC-237.re000066400000000000000000000003071513171467200172320ustar00rootroot00000000000000retrieve, area=90/-180/-90/180,class=od,date=2024-01-01,expver=1,grid=0.25/0.25,levtype=sfc,padding=0,param=mslp,step=0/to/120/by/3,stream=oper,time=00:00,type=fc, target="reference.Hx2aUM.data" metkit-1.16.0/tests/expand/MARSC-240.expected000066400000000000000000000007221513171467200204200ustar00rootroot00000000000000RETRIEVE, CLASS = OD, TYPE = OF, STREAM = OCEA, EXPVER = 0001, REPRES = SH, LEVTYPE = DP, LEVELIST = 0, PARAM = 151145, DATE = 20070601, TIME = 0000, RANGE = 264, STEP = 288, NUMBER = 0, DOMAIN = G, SYSTEM = 2, METHOD = 1, PRODUCT = TIMS, SECTION = Z, LATITUDE = -9.967, TARGET = reference.0DY4f2.data metkit-1.16.0/tests/expand/MARSC-240.req000066400000000000000000000003601513171467200174040ustar00rootroot00000000000000retrieve, DOMAIN=G,LEVTYPE=DP,DATE=20070601,TIME=0000,STEP=288,PARAM=145.151,CLASS=OD,TYPE=OF,STREAM=OCEA,EXPVER=0001,NUMBER=0,SYSTEM=2,METHOD=1,PRODUCT=TIMS,SECTION=Z,LEVELIST=0.000,LATITUDE=-9.967,RANGE=264, target="reference.0DY4f2.data"metkit-1.16.0/tests/expand/MARSC-241.expected000066400000000000000000000004711513171467200204220ustar00rootroot00000000000000RETRIEVE, CLASS = RD, TYPE = FC, STREAM = OPER, EXPVER = f36f, REPRES = SH, LEVTYPE = ML, LEVELIST = 1, PARAM = 210073/210074, DATE = 20041015, TIME = 1200, STEP = 0, DOMAIN = G, TARGET = reference.datametkit-1.16.0/tests/expand/MARSC-241.req000066400000000000000000000002431513171467200174050ustar00rootroot00000000000000retrieve, DOMAIN=G,LEVTYPE=ML,LEVELIST=1,DATE=20041015,TIME=1200,STEP=0,PARAM=73.210/74.210,CLASS=RD,TYPE=FC,STREAM=OPER,EXPVER=f36f, target=reference.datametkit-1.16.0/tests/expand/MARSC-242.expected000066400000000000000000000003771513171467200204300ustar00rootroot00000000000000RETRIEVE, CLASS = E4, TYPE = CL, STREAM = MODA, EXPVER = 0001, REPRES = SH, LEVTYPE = ML, LEVELIST = 1, PARAM = 155, DATE = JAN, DOMAIN = G, TARGET = reference.datametkit-1.16.0/tests/expand/MARSC-242.req000066400000000000000000000002101513171467200174000ustar00rootroot00000000000000retrieve, DOMAIN=G,LEVTYPE=ML,LEVELIST=1,DATE=JAN,PARAM=155.128,CLASS=E4,TYPE=CL,STREAM=MODA,EXPVER=0001, target=reference.data metkit-1.16.0/tests/expand/MARSC-244.expected000066400000000000000000000006021513171467200204210ustar00rootroot00000000000000RETRIEVE, CLASS = TI, TYPE = PF, STREAM = ENFO, EXPVER = test, MODEL = LAM, REPRES = SH, LEVTYPE = SFC, PARAM = 166, DATE = 20130225, TIME = 0000, STEP = 3, NUMBER = 1, ORIGIN = SRNWPPEPS-DWD-EUA, TARGET = reference.data, PADDING = 0, PROCESS = LOCALmetkit-1.16.0/tests/expand/MARSC-244.req000066400000000000000000000002621513171467200174110ustar00rootroot00000000000000retrieve, DATE=20130225,TIME=0000,ORIGIN=SRNWPPEPS-DWD-EUA,STEP=3,LEVTYPE=SFC,NUMBER=1,PARAM=166,EXPVER=test,CLASS=TI,MODEL=LAM,TYPE=PF,STREAM=ENFO, target=reference.datametkit-1.16.0/tests/expand/MARSC-245.expected000066400000000000000000000006241513171467200204260ustar00rootroot00000000000000RETRIEVE, CLASS = MS, COUNTRY = IT, MODEL = HRM, BCMODEL = IFS, ICMODEL = MVOI, DOMAIN = EUROATL, STREAM = OPER, TYPE = FG, EXPVER = 0001, LEVTYPE = 110, PARAM = 201033, TIME = 1800, DATE = 20040102, STEP = 6, LEVELIST = 1, TARGET = reference.data, GRIB = ECMWFmetkit-1.16.0/tests/expand/MARSC-245.req000066400000000000000000000003221513171467200174070ustar00rootroot00000000000000retrieve, DOMAIN=EUROATL,LEVTYPE=110,LEVELIST=1,DATE=20040102,TIME=1800,STEP=6,PARAM=33.201,CLASS=MS,TYPE=FG,STREAM=OPER,EXPVER=0001,COUNTRY=IT,MODEL=HRM,BCMODEL=IFS,ICMODEL=MVOI, target=reference.data metkit-1.16.0/tests/expand/MARSC-247.expected000066400000000000000000000005071513171467200204300ustar00rootroot00000000000000RETRIEVE, CLASS = RD, TYPE = AN, STREAM = OPER, EXPVER = aaaa, REPRES = SH, LEVTYPE = PL, LEVELIST = 1000/850/700/500/400/300, PARAM = 129, DATE = 20250413, TIME = 1200, STEP = 0, DOMAIN = G, TARGET = data.reference metkit-1.16.0/tests/expand/MARSC-247.req000066400000000000000000000001261513171467200174130ustar00rootroot00000000000000 retrieve, class=rd, date=20250413, expver=aaaa, target=data.referencemetkit-1.16.0/tests/expand/MARSC-248.expected000066400000000000000000000005131513171467200204260ustar00rootroot00000000000000RETRIEVE, CLASS = OD, TYPE = AN, STREAM = OPER, EXPVER = 0001, REPRES = SH, LEVTYPE = PL, LEVELIST = 1000/500, PARAM = 130, DATE = 20250416, TIME = 1200, STEP = 0, DOMAIN = G, TARGET = data.reference, ACCURACY = 8 metkit-1.16.0/tests/expand/MARSC-248.req000066400000000000000000000001721513171467200174150ustar00rootroot00000000000000retrieve, levtype=pl, level=1000/500, date=20250416, param=t, accuracy=LOW, target=data.reference metkit-1.16.0/tests/expand/MARSC-249.expected000066400000000000000000000005701513171467200204320ustar00rootroot00000000000000RETRIEVE, CLASS = OD, TYPE = AN, STREAM = OPER, EXPVER = 0001, REPRES = SH, LEVTYPE = PL, LEVELIST = 1000/500, PARAM = 130, DATE = 20250416, TIME = 1200, STEP = 0, DOMAIN = G, TARGET = data.reference, RESOL = AUTO, ACCURACY = 8, GRID = 5/5 metkit-1.16.0/tests/expand/MARSC-249.req000066400000000000000000000002141513171467200174130ustar00rootroot00000000000000retrieve, levtype=pl, level=1000/500, date=20250416, param=t, accuracy=REDUCED, grid=5/5, target=data.reference metkit-1.16.0/tests/expand/MARSC-251.expected000066400000000000000000000005641513171467200204260ustar00rootroot00000000000000RETRIEVE, CLASS = TI, TYPE = CF, STREAM = ENFO, EXPVER = ALL, REPRES = SH, LEVTYPE = SFC, PARAM = 167, DATE = 20250414, TIME = 1200, STEP = 24, ORIGIN = ALL, TARGET = data.reference, PADDING = 0, PROCESS = LOCAL, EXPECT = ANY, NUMBER = 0metkit-1.16.0/tests/expand/MARSC-251.req000066400000000000000000000003141513171467200174050ustar00rootroot00000000000000retrieve, class=ti, date=20250414, time=12, origin=all, expver=all, type=cf, stream=enfo, levtype=sfc, param=2t, step=24, expect=any, target=data.reference metkit-1.16.0/tests/expand/MARSC-252.expected000066400000000000000000000004351513171467200204240ustar00rootroot00000000000000RETRIEVE, CLASS = OD, TYPE = AN, STREAM = OPER, EXPVER = 0001, REPRES = GG, LEVTYPE = SFC, PARAM = 164, DATE = 20250416, TIME = 0000, STEP = 0, DOMAIN = G, TARGET = data.reference metkit-1.16.0/tests/expand/MARSC-252.req000066400000000000000000000004101513171467200174030ustar00rootroot00000000000000retrieve, class=od, stream=da, type=an, levtype=sfc, levelist=off, resol=off, date=20250416, time=00, step=00, param=tcc/10u/10v/2t/msl, param=tcc, repres=gg, format=p, expver=0001, target=data.reference metkit-1.16.0/tests/expand/MARSC-253.expected000066400000000000000000000004421513171467200204230ustar00rootroot00000000000000RETRIEVE, CLASS = OD, TYPE = TF, STREAM = ENFO, EXPVER = 0001, REPRES = BU, OBSTYPE = 32, DATE = 20060112, TIME = 0000/1200, STEP = 0, DOMAIN = G, TARGET = data.reference, DUPLICATES = KEEP metkit-1.16.0/tests/expand/MARSC-253.req000066400000000000000000000003121513171467200174050ustar00rootroot00000000000000retrieve, class=od, type=tf, stream=enfo, expver=0001, repres=bu, obstype=32, date=20060112, time=0000/1200, domain=g, duplicates=keep, target=data.reference metkit-1.16.0/tests/expand/MARSC-254.expected000066400000000000000000000004371513171467200204300ustar00rootroot00000000000000RETRIEVE, CLASS = OD, TYPE = OB, STREAM = OPER, EXPVER = 0001, REPRES = BU, OBSTYPE = 1, DATE = 20250414, TIME = 0000, RANGE = 1439, DOMAIN = G, TARGET = data.reference, DUPLICATES = KEEP metkit-1.16.0/tests/expand/MARSC-254.re000066400000000000000000000001331513171467200172260ustar00rootroot00000000000000retrieve, type=ob, date=-3, time=00, range=1439, target=data.reference metkit-1.16.0/tests/expand/MARSC-255.expected000066400000000000000000000006371513171467200204330ustar00rootroot00000000000000RETRIEVE, CLASS = OD, TYPE = AN, STREAM = OPER, EXPVER = 0001, REPRES = SH, LEVTYPE = ML, LEVELIST = 50, PARAM = 248, DATE = 20250416, TIME = 1200, STEP = 0, DOMAIN = G, TARGET = data.reference, RESOL = AUTO, INTERPOLATION = BILINEAR, AREA = 75/60/10/-20, GRID = 2.5/2.5 metkit-1.16.0/tests/expand/MARSC-255.req000066400000000000000000000002541513171467200174140ustar00rootroot00000000000000retrieve, date=20250416, area=75/60/10/-20, grid=2.5/2.5, levtype=ml, levelist=50, param=248, interpolation=bilinear, target=data.reference metkit-1.16.0/tests/expand/MARSC-258.expected000066400000000000000000000005351513171467200204330ustar00rootroot00000000000000RETRIEVE, CLASS = RD, TYPE = FC, STREAM = LWDA, EXPVER = h3f7, REPRES = SH, LEVTYPE = PL, LEVELIST = 1000/850/700/500/400/300, PARAM = 129, DATE = 20181101, TIME = 0000, STEP = ALL, ANOFFSET = 9, DOMAIN = G, TARGET = data.reference metkit-1.16.0/tests/expand/MARSC-258.req000066400000000000000000000002571513171467200174220ustar00rootroot00000000000000retrieve, class=rd, stream=lwda, levtype=pl, type=fc, expver=h3f7, step=all, anoffset=9, time=00, date=20181101, target=data.reference metkit-1.16.0/tests/expand/MARSC-261.expected000066400000000000000000000006321513171467200204230ustar00rootroot00000000000000 RETRIEVE, CLASS = OD, TYPE = PF, STREAM = ENFO, EXPVER = 0001, REPRES = SH, LEVTYPE = SFC, PARAM = 167/165/166/164/228, DATE = 20250416, TIME = 0000, STEP = 6/12, NUMBER = 1/2, DOMAIN = G, TARGET = data.reference, RESOL = N128, AREA = 70.5/-21/30/40.5, GRID = 1.5/1.5metkit-1.16.0/tests/expand/MARSC-261.re000066400000000000000000000004561513171467200172340ustar00rootroot00000000000000 retrieve, class=od, type=pf, stream=ef, expver=0001, repres=sh, levtype=sfc, param=167/165/166/164/228, date=20250416, time=0000, step=6/12, number=1/2, domain=g, resol=n128, area=70.5/-21.0/30.0/40.5, grid=1.5/1.5, target=data.referencemetkit-1.16.0/tests/expand/MARSC-263.expected000066400000000000000000000007401513171467200204250ustar00rootroot00000000000000RETRIEVE, CLASS = OD, TYPE = OF, STREAM = OCEA, EXPVER = 0001, REPRES = SH, LEVTYPE = DP, LEVELIST = 0/5, PARAM = 129/130/145, DATE = 20120101, TIME = 0000, STEP = 24/48/72/96, NUMBER = 0/1/2/3/4, DOMAIN = G, SYSTEM = 3, METHOD = 1, PRODUCT = INST, SECTION = H, TARGET = data.reference, DATABASE = marsod, EXPECT = 60metkit-1.16.0/tests/expand/MARSC-263.req000066400000000000000000000005031513171467200174100ustar00rootroot00000000000000retrieve, levelist=0/5, section=h, stream=ocea, system=3, method=1, number=0/to/4, time=00, levtype=dp, product=inst, expver=1, param=129/130/145, class=od, date=20120101, type=of, step=24/to/96/by/24, expect=60, database=marsod, target=data.referencemetkit-1.16.0/tests/expand/MARSC-264.expected000066400000000000000000000006401513171467200204250ustar00rootroot00000000000000 RETRIEVE, CLASS = OD, TYPE = FCMAX, STREAM = SFMM, EXPVER = 0001, REPRES = GG, LEVTYPE = SFC, PARAM = 167, DATE = 19911001, FCMONTH = 2/3/4, TIME = 0000, NUMBER = 0/1/2/3/4, DOMAIN = G, SYSTEM = 2, METHOD = 1, SOURCE = mod.cl.surface, TARGET = data.reference, DATABASE = filemetkit-1.16.0/tests/expand/MARSC-264.req000066400000000000000000000004531513171467200174150ustar00rootroot00000000000000retrieve, class=od, type=fcmax, stream=sfmm, expver=0001, repres=gg, levtype=sfc, param=167, date=19911001, fcmonth=02/03/04, time=0000, number=0/1/2/3/4, domain=g, system=02, method=01, source="mod.cl.surface", target="data.reference"metkit-1.16.0/tests/expand/MARSC-267 copy.expected000066400000000000000000000012011513171467200213550ustar00rootroot00000000000000RETRIEVE, CLASS = S2, TYPE = PF, STREAM = ENFH, EXPVER = prod, REPRES = SH, LEVTYPE = PL, LEVELIST = 200/300/500/700/850/925/1000, PARAM = 130, DATE = 20240111, HDATE = 2004-01-11, TIME = 0000, STEP = 0/24/48/72/96/120/144/168/192/216/240/264/288/312/336/360/384/408/432/456/480/504/528/552/576/600/624/648/672/696/720/744/768/792/816/840/864/888/912/936/960/984/1008/1032/1056/1080/1104, NUMBER = 1, ORIGIN = ECMF, TARGET = target.out, AREA = 40/-180/-40/180, PADDING = 0, PROCESS = LOCALmetkit-1.16.0/tests/expand/MARSC-267.expected000066400000000000000000000011471513171467200204330ustar00rootroot00000000000000RETRIEVE, CLASS = S2, TYPE = PF, STREAM = ENFH, EXPVER = prod, REPRES = SH, LEVTYPE = PL, LEVELIST = 200/300/500/700/850/925/1000, PARAM = 130, DATE = 20240111, HDATE = 20040111, TIME = 0000, STEP = 0/24/48/72/96/120/144/168/192/216/240/264/288/312/336/360/384/408/432/456/480/504/528/552/576/600/624/648/672/696/720/744/768/792/816/840/864/888/912/936/960/984/1008/1032/1056/1080/1104, NUMBER = 1, ORIGIN = ECMF, TARGET = target.out, AREA = 40/-180/-40/180, PADDING = 0metkit-1.16.0/tests/expand/MARSC-267.req000066400000000000000000000003661513171467200174230ustar00rootroot00000000000000retrieve,area=40/-180/-40/180,class=s2,date=2024-01-11,expver=prod,levtype=pl,padding=0,param=130,step=0/to/1104/by/24,stream=enfh,time=00:00:00,type=pf,levelist=200/300/500/700/850/925/1000,number=1,origin=ecmf,hdate=2004-01-11,target=target.outmetkit-1.16.0/tests/marsgen/000077500000000000000000000000001513171467200157015ustar00rootroot00000000000000metkit-1.16.0/tests/marsgen/CMakeLists.txt000066400000000000000000000005231513171467200204410ustar00rootroot00000000000000 list( APPEND marsgen_tests simple compare obs legacy) foreach( _test ${marsgen_tests} ) configure_file( metkit_marsgen_${_test}.sh.in metkit_marsgen_${_test}.sh @ONLY ) ecbuild_add_test( TYPE SCRIPT CONDITION HAVE_BUILD_TOOLS COMMAND metkit_marsgen_${_test}.sh ) endforeach()metkit-1.16.0/tests/marsgen/genfile000066400000000000000000000006751513171467200172450ustar00rootroot00000000000000verb, retrieve@expver = 9999, archive@expver = 9999, retrieve@class = EA, archive@class = EA, retrieve@stream = LWDA, archive@stream = DA, class=EA, stream=LWDA, expver=1001, type=analysis,anoffset=3, param=129/152/130/138/155/75/76/133/203.128/246/247/248, levtype=modellevels, levels=1/to/137, pass="runda", date=20200601, time=06, step=00 metkit-1.16.0/tests/marsgen/genfile.default000066400000000000000000000005501513171467200206600ustar00rootroot00000000000000verb, default@expver = 9999, default@class = EA, default@stream = LWDA, class=EA, stream=LWDA, expver=1001, type=analysis,anoffset=3, param=129/152/130/138/155/75/76/133/203.128/246/247/248, levtype=modellevels, levels=1/to/137, pass="runda", date=20200601, time=06, step=00 metkit-1.16.0/tests/marsgen/genfile.legacy000066400000000000000000000007111513171467200204770ustar00rootroot00000000000000verb, fdb_retrieve@expver = 9999, archive@expver = 9999, fdb_retrieve@class = EA, archive@class = EA, fdb_retrieve@stream = LWDA, archive@stream = DA, class=EA, stream=LWDA, expver=1001, type=analysis,anoffset=3, param=129/152/130/138/155/75/76/133/203.128/246/247/248, levtype=modellevels, levels=1/to/137, pass="runda", date=20200601, time=06, step=00 metkit-1.16.0/tests/marsgen/metkit_marsgen_compare.sh.in000077500000000000000000000016431513171467200233700ustar00rootroot00000000000000#!/bin/bash set -uex [ -e outfile.compare ] && rm outfile.compare MARSGEN="@CMAKE_BINARY_DIR@/bin/mars-archive-script" GENFILE="@CMAKE_CURRENT_SOURCE_DIR@/genfile" OUTFILE="outfile.compare" CHECKFILE="checkfile.compare" $MARSGEN < $GENFILE > $OUTFILE cat << EOF > $CHECKFILE \$RETRIEVE_MARS << @ retrieve, class=EA, stream=LWDA, expver=9999, type=analysis, anoffset=3, param=129/152/130/138/155/75/76/133/203.128/246/247/248, levtype=modellevels, levels=1/to/137, pass=runda, date=20200601, time=06, step=00, target=mars.source.0 @ \$RETRIEVE_COMPLETE \$UNBLOCK mars.source.0 mars.archive.0 \$ARCHIVE_MARS << @ archive, class=EA, stream=DA, expver=9999, type=analysis, anoffset=3, param=129/152/130/138/155/75/76/133/203.128/246/247/248, levtype=modellevels, levels=1/to/137, pass=runda, date=20200601, time=06, step=00, source=mars.archive.0 @ \$ARCHIVE_COMPLETE EOF cmp $CHECKFILE $OUTFILEmetkit-1.16.0/tests/marsgen/metkit_marsgen_legacy.sh.in000077500000000000000000000016621513171467200232070ustar00rootroot00000000000000#!/bin/bash set -uex [ -e outfile.legacy ] && rm outfile.legacy MARSGEN="@CMAKE_BINARY_DIR@/bin/mars-archive-script" GENFILE="@CMAKE_CURRENT_SOURCE_DIR@/genfile.legacy" OUTFILE="outfile.legacy" CHECKFILE="checkfile.legacy" $MARSGEN --in="$GENFILE" --out="$OUTFILE" cat << EOF > $CHECKFILE \$RETRIEVE_MARS << @ retrieve, class=EA, stream=LWDA, expver=9999, type=analysis, anoffset=3, param=129/152/130/138/155/75/76/133/203.128/246/247/248, levtype=modellevels, levels=1/to/137, pass=runda, date=20200601, time=06, step=00, target=mars.source.0 @ \$RETRIEVE_COMPLETE \$UNBLOCK mars.source.0 mars.archive.0 \$ARCHIVE_MARS << @ archive, class=EA, stream=DA, expver=9999, type=analysis, anoffset=3, param=129/152/130/138/155/75/76/133/203.128/246/247/248, levtype=modellevels, levels=1/to/137, pass=runda, date=20200601, time=06, step=00, source=mars.archive.0 @ \$ARCHIVE_COMPLETE EOF cmp $CHECKFILE $OUTFILE metkit-1.16.0/tests/marsgen/metkit_marsgen_obs.sh.in000077500000000000000000000011711513171467200225210ustar00rootroot00000000000000#!/bin/bash set -uex [ -e outfile.obs ] && rm outfile.obs MARSGEN="@CMAKE_BINARY_DIR@/bin/mars-archive-script" GENFILE="@CMAKE_CURRENT_SOURCE_DIR@/genfile" OUTFILE="outfile.obs" CHECKFILE="checkfile.obs" $MARSGEN --obs < $GENFILE > $OUTFILE cat << EOF > $CHECKFILE \$PREOBS \$header.1 \$data.1 mars.archive.0 \$ARCHIVE_MARS << @ archive, class=EA, stream=DA, expver=9999, type=analysis, anoffset=3, param=129/152/130/138/155/75/76/133/203.128/246/247/248, levtype=modellevels, levels=1/to/137, pass=runda, date=20200601, time=06, step=00, source=mars.archive.0 @ \$ARCHIVE_COMPLETE EOF cmp $CHECKFILE $OUTFILE metkit-1.16.0/tests/marsgen/metkit_marsgen_simple.sh.in000077500000000000000000000016531513171467200232340ustar00rootroot00000000000000#!/bin/bash set -uex [ -e outfile.simple ] && rm outfile.simple MARSGEN="@CMAKE_BINARY_DIR@/bin/mars-archive-script" GENFILE="@CMAKE_CURRENT_SOURCE_DIR@/genfile" OUTFILE="outfile.simple" CHECKFILE="checkfile.simple" $MARSGEN --in="$GENFILE" --out="$OUTFILE" cat << EOF > $CHECKFILE \$RETRIEVE_MARS << @ retrieve, class=EA, stream=LWDA, expver=9999, type=analysis, anoffset=3, param=129/152/130/138/155/75/76/133/203.128/246/247/248, levtype=modellevels, levels=1/to/137, pass=runda, date=20200601, time=06, step=00, target=mars.source.0 @ \$RETRIEVE_COMPLETE \$UNBLOCK mars.source.0 mars.archive.0 \$ARCHIVE_MARS << @ archive, class=EA, stream=DA, expver=9999, type=analysis, anoffset=3, param=129/152/130/138/155/75/76/133/203.128/246/247/248, levtype=modellevels, levels=1/to/137, pass=runda, date=20200601, time=06, step=00, source=mars.archive.0 @ \$ARCHIVE_COMPLETE EOF cmp $CHECKFILE $OUTFILE metkit-1.16.0/tests/netcdf/000077500000000000000000000000001513171467200155105ustar00rootroot00000000000000metkit-1.16.0/tests/netcdf/CMakeLists.txt000066400000000000000000000022711513171467200202520ustar00rootroot00000000000000# two_dimensions_merge list(APPEND merge_tests_ok simple_two_way_merge simple_three_way_merge complex_two_way_merge type_upgrade_merge attribute_merge multi_merge multi_dimensions_merge signature_merge_1 signature_merge_2 new_missing_values_merge new_dimension_merge_1 new_dimension_merge_2 retype_merge coordinates_overlap_merge_1 coordinates_overlap_merge_2 coordinates_overlap_merge_3 coordinates_overlap_merge_4 coordinates_overlap_merge_5 coordinates_overlap_merge_6 date_merge_1 date_merge_2 variable_merge_1 variable_merge_2 variable_merge_3 variable_merge_4 variable_merge_5 bounds_merge_1 bounds_merge_2 monotonic ) list(APPEND merge_tests_fail bounds_merge) list(APPEND merge_tests_only coordinates_overlap_merge) foreach(_TEST bounds_merge_2 # ${merge_tests_ok} ) ecbuild_add_test( TARGET "nccombine_${_TEST}" ENVIRONMENT "${metkit_env}" COMMAND "${CMAKE_CURRENT_SOURCE_DIR}/${_TEST}.sh") endforeach() metkit-1.16.0/tests/netcdf/attribute_merge.sh000077500000000000000000000021611513171467200212310ustar00rootroot00000000000000#!/bin/bash set -eaux ncgen -b - <C–C–€C–C–metkit-1.16.0/tests/netcdf/two_dimensions_merge.sh000077500000000000000000000014451513171467200222730ustar00rootroot00000000000000#!/bin/bash set -eaux ncgen -b - < aux $check aux out diff ok out metkit-1.16.0/tests/regressions/METK-103/corrupted000066400000000000000000001040221513171467200216020ustar00rootroot00000000000000BUFR¡Òb€Ë!4Ë~hbçDiËf7aîn†ˆA˜Æ´.¡Òd jF ´ÀÌF¡r €(!EÆ,õp @ €`€€ 0(bPÄÀ€ @(€`` €&(P 0@€@ („Q¢0D€‰@ 0`À@€ €€ 0(`øÂ„ €€ $J0˜pà À`€8 pHà Á`ƒ€:8xpøâÄ ˆ€€$J8˜€ `€ @ €H `€ @@€ˆ ` € .@`€È `€ >@€ ` €&$H @@ € €$H(X ÀA ƒ€ €$"HH˜!@B …€ €$2HhØ!ÀC ‡€ € $BHˆ‘"@D ‰€ €(P   @P€ÀÀ  (P, `@ÐÀÀ ($PL  AP‚ÀÀ (4Pl àAЃÀÀ !(DPŒ¡ BP„À À €,X°(``Àà‚ € ,X0°h`àÁà„ €,&XP°¨a`Âà† €,6Xp°èaàÃàˆ €",FX±(b`Äà€ €0 `À8€€ € € 0`8Àx € €0*`XÀ¸€ € €0:`xÀø‚ € €$0J`˜Á8‚€@ €€ €4 hÐ8 €A ‚€ € 4h8Ðx¡B „€ €4*hXи¡€C †€ €4:hxÐø¢D ˆ€ €$4Jh˜Ñ8¢€€ €€8 pà8À€ €€ 8p8àxÁ‚ € €8*pXà¸Á€ƒ € €8:pxàøÂ„ €€$8Jp˜á8„ˆt)è’!ѤC¤H‡J‘™":D:„ˆu)ê’!Õ¤C¬H‡Z‘¹"zD;ˆv)ì’!Ù¤C´H‡j‘Ù"ºD;„ˆw)î’!ݤC¼H‡z‘ù"úD<ˆx)ð’!á¤CÄH‡Š‘":D<„ˆy)hR"Ñ$E£H‹H‘•"-2DZtˆµ jR"Õ$E«H‹X‘µ"-rDZôˆ¶ lR"Ù$E³H‹h‘Õ"-²D[tˆ· nR"Ý$E»H‹x‘õ"-òD[ôˆ¸ pR"á$EÃH‹ˆ‘".2D\tˆ¹ rR#Ð$G¡HD‘"="DzTˆôÉéÒ#Ô$G©HT‘­"=bDzÔˆõÉëÒ#Ø$G±Hd‘Í"=¢D{TˆöÉíÒ#Ü$G¹Ht‘í"=âD{Ôˆ÷ÉïÒ#à$GÁH„‘ ">"D|TˆøÉñÒ#ä$GÉH”‘&}"MDš‰4IhÒ$Ò$I¥H“L‘&"MBDš”‰5IjÒ$Ö$I­H“\‘&½"M‚D›‰6IlÒ$Ú$IµH“l‘&Ý"MÂD›”‰7InÒ$Þ$I½H“|‘&ý"NDœ‰8IpÒ$â$IÅH“Œ‘'"NBDœ”‰9IrÒ%ϤK H—B‘.‰"]DºD‰t©é’%Ó¤K¨H—R‘.©"]ZDºÄ‰u©ë’%פK°H—b‘.É"]šD»D‰v©í’%Û¤K¸H—r‘.é"]ÚD»Ä‰w©ï’%ߤKÀH—‚‘/ "^D¼D‰x©ñ’%ã¤KÈH—’‘/)"^ZD¼Ä‰´ hR&Ñ$M£H›H‘6•"m2DÚt‰µ jR&Õ$M«H›X‘6µ"mrDÚô‰¶ lR&Ù$M³H›h‘6Õ"m²DÛt‰· nR&Ý$M»H›x‘6õ"mòDÛô‰¸ pR&á$MÃH›ˆ‘7"n2DÜt‰¹ rR&å$MËH›˜‘>…"}Dú4‰ô‰éR'Ó$O§HŸP‘>¥"}RDú´‰õ‰ëR'×$O¯HŸ`‘>Å"}’Dû4‰ö‰íR'Û$O·HŸp‘>å"}ÒDû´‰÷‰ïR'ß$O¿HŸ€‘?"~Dü4‰ø‰ñR'ã$OÇHŸ‘?%"~RDü´‰ù‰óR(Ñ$Q£H£H‘F•"2EtŠ5 jR(Õ$Q«H£X‘Fµ"rEôŠ6 lR(Ù$Q³H£h‘FÕ"²EtŠ7 nR(Ý$Q»H£x‘Fõ"òEôŠ8 pR(á$QÃH£ˆ‘G"Ž2EtŠ9 rR(å$QËH£˜‘G5"ŽrE:4Št‰éR)Ó$S§H§P‘N¥"RE:´Šu‰ëR)×$S¯H§`‘NÅ"’E;4Šv‰íR)Û$S·H§p‘Nå"ÒE;´Šw‰ïR)ß$S¿H§€‘O"žE<4Šx‰ñR)ã$SÇH§‘O%"žRE<´Šy‰óR)ç$SÏH«H‘V•"­2EZtе jR*Õ$U«H«X‘Vµ"­rEZôж lR*Ù$U³H«h‘VÕ"­²E[tŠ· nR*Ý$U»H«x‘Võ"­òE[ôЏ pR*á$UÃH«ˆ‘W"®2E\tй rR*å$UËH«˜‘W5"®rE\ôŠº tR+Ò¤W¦H¯N‘^¡"½JEz¤Šõië+Ö¤W®H¯^‘^Á"½ŠE{$Šöií+Ú¤W¶H¯n‘^á"½ÊE{¤Š÷iï+Þ¤W¾H¯~‘_"¾ E|$Šøiñ+â¤WÆH¯Ž‘_!"¾JE|¤Šùió+æ¤WÎH¯ž‘_A"¾ŠE}$‹4ÉiÒ,Ô$Y©H³T‘f­"ÍbEšÔ‹5ÉkÒ,Ø$Y±H³d‘fÍ"Í¢E›T‹6ÉmÒ,Ü$Y¹H³t‘fí"ÍâE›Ô‹7ÉoÒ,à$YÁH³„‘g "Î"EœT‹8ÉqÒ,ä$YÉH³”‘g-"ÎbEœÔ‹9ÉsÒ,è$YÑH³¤‘gK"ΚE<‹ZY´Ò-iäZÔH·L‘n"ÝBEº”‹uIêÒ-Ö$[­H·\‘n½"Ý‚E»‹vIìÒ-Ú$[µH·l‘nÝ"ÝÂE»”‹wIîÒ-Þ$[½H·|‘ný"ÞE¼‹xIðÒ-â$[ÅH·Œ‘o"ÞBE¼”‹yIòÒ-æ$[ÍH·œ‘o="Þ‚E½‹zIô²-é¤[ÓÈ·¨‘oS"ÞªEÍ$‹šY4Ò.iä\ÔH¹©‘sU"æ®EÚt‹µ jR.Õ$]«H»X‘vµ"írEÚô‹¶ lR.Ù$]³H»h‘vÕ"í²EÛt‹· nR.Ý$]»H»x‘võ"íòEÛô‹¸ pR.á$]ÃH»ˆ‘w"î2EÜt‹¹ rR.å$]ËH»˜‘w5"îrEÜô‹º tR.èä]ÒH»¥‘wM"îžEÝD‹º™uR.êä]ÖH½£‘{I"ö–Eí4‹Úyµ/jd^ÕH½«‘{Y"ö¶Eít‹õ êR/Õ$_«H¿X‘~µ"ýrEúô‹ö ìR/Ù$_³H¿h‘~Õ"ý²Eût‹÷ îR/Ý$_»H¿x‘~õ"ýòEûô‹ø ðR/á$_ÃH¿ˆ‘"þ2Eüt‹ù òR/å$_ËH¿˜‘5"þrEüô‹ú ôR/é$_ÓH¿§‘Q"þ¦EýT‹ú¹õ’/ëd_×H¿¯‘a#–F 4Œy50jd`ÕHÁ«‘ƒY#¶F tŒù60lda¨HÃR‘†©# ZFÄŒ5©k’0פa°HÃb‘†É# šFDŒ6©m’0Û¤a¸HÃr‘†é# ÚFÄŒ7©o’0ߤaÀH‘‡ #FDŒ8©q’0ã¤aÈHÃ’‘‡)#ZFÄŒ9©s’0ç¤aÐH⑇I#šF<Œ:‰u20ê¤aÕÈ쑇[#ºF|Œ; v20ì¤aÙÈÅ ‘‹M#žF-DŒZ™µR1jäbÖHÅ­‘‹]#¾F-„Œ[¶R1läbÚHÇR‘Ž©#ZF:ÄŒu©ë’1פc°HÇb‘ŽÉ#šF;DŒv©í’1Û¤c¸HÇr‘Žé#ÚF;ÄŒw©ï’1ߤcÀHÇ‚‘ #FF|DŒø©ñ’3ã¤gÈHÓT‘¦­#MbFšÔ5ÉkÒ4Ø$i±HÓd‘¦Í#M¢F›T6ÉmÒ4Ü$i¹HÓt‘¦í#MâF›Ô7ÉoÒ4à$iÁHÓ„‘§ #N"FœT8ÉêÒ5Ö$k­H×\‘®½#]‚F»vIìÒ5Ú$kµH×l‘®Ý#]ÂF»”wIîÒ5Þ$k½H×|‘®ý#^F¼xIðÒ5â$kÅHÛ^‘¶Á#mŠFÛ$¶im6Ú¤m¶HÛn‘¶á#mÊFÛ¤·io6Þ¤m¾HÛ~‘·#n FÜ$¸iq7Ù$o³Hßh‘¾Õ#}²Fût÷ îR7Ý$o»Hßx‘¾õ#}òFûôø ðR7á$oÃHãh‘ÆÕ#²GtŽ7 nR8Ý$q»Hãx‘Æõ#òGôŽ8 pR8á$qÃHçl‘ÎÝ#ÂG;”ŽwIîÒ9Þ$s½Hç|‘Îý#žG<ŽxImÒ:Ü$u¹Hët‘Öí#­âG[ÔŽ·ÉoÒ:à$uÁHë„‘Þá#½ÊG{¤Ž÷iï;Þ¤w¾Hï~‘ß#¾ G|$7InÒ<Þ$y½Hó|‘æý#ÎGœ8IîÒ=Þ${½H÷|‘îý#ÞG¼xIo>Þ¤}¾Hû~‘÷#î GÜ$÷©ï’?ߤÀHÿ‚‘ÿ $ úH8) p’AःÂI †- ÌÀà!݇¸¨ýè˜BDÜ[~ôXä%Ô`Ù{(B‡BDÜ­€©¡žð@Íx-€?†‚-ëÀ£“}Ü…:DB‡"ÛqÁ‚ê šÐy „)<$W!;# œhZýÃÂ>¾‚[vt†ÊDO9#?p-P›T^ &ZØ%äGŠ ÿ ^ƒ!“!×$\{ü£ø ‹A ‡H†E»`Çg|I! ³ èNÕB§~ŰÂb†t¼6³!Î5ÀÕýFá†8—Ñ ëˆzvìe )™zmžDø@ZŃ7ÔÅ þ—·@KÔ‚xð¼T†DL55áÂÕ¨|ÇÄv"Cám UØMÂB†•ùˆ­óE¡.‘á€Ý i¼fg£Kò$pßPÇ,":êÑãÊ€À"ä³!TÑÓÁS  mÊP!_Á#h ÞUÙLQÎÖØX9ÖAç5üø†Äa®$—10û êHRe«Ê#ø·FÅë<0æÁ“„ þôk #q@Nàè¤Gv¾=AAöq\ƒÌ¤7"@'gkÞ åsHƒûì"ì¡/Ï AÈX(Âò~Õ X;fAóœaÀ‰5z®%_17GЬSõ¸J‡0ºfÆn1®Á™Ý 1¼l¡c}Ù´pëÐǾ> aü±I$…\¤C³ŒØ*A„z ªpyˆ„-ì$|¡Õò {ˆ†ïÀž³`3©Î÷€‹ñÁ0)ÁaR Íàd‰ƒU„2ÀíׇÑ,A–¢%Qïh•œÞ(zP.ŠãäZ2¢ê0Æà†hn4Í1²Ä ùXrÞC¯ÀBàøJ‡ó¾A*Ò±À5À’T0´Á¶z:p†„‘ì'œ¡UO na=Lt çÖ¡ @BgŽˆ’›DÆ'»áJ- ³ØX¯"Þ·ÃÙ†Ph4 ¬ÂÈ„qZã¤âõC‡ÛT@i–àP » †.óø-ºAž¦{Ðú„bD&aIe x^ŽC%ª³ðáí‡qx>™ d0š„®>&û±D+ŠƒhW.ÂÒV8ÀØÆ7þ3KA¦Á ˜oÚc—ˆ ò<‡Ã?¥Â ˆ¯| >`z]•p*¹†  » z28$Ÿ=b ®`[š ÖõPÛ߇Al=âaÏ Œ –8&;>ŠS\U®bÆ(ö ½Ø *2‹ ¦hnSËS!ï5‡ªä>äz ‡ àUsnè!‹<þ ng©ƒžôþ¡‘ ‡ØRYBÞ£Éj†¬ü8{aÜ^¦@ƒYL#æ¡+‰¾ìQ â Ú˰´„…ÕŽ061ÿŒÒÐi°Cfö˜åâ`H¡üïJ´…lDD0À`àŠ€0|åŒ3`ªè6©Áæ"·°‘ò„ñ<*—!m# -øgŠCm&òðó̈8C1TO€˜£ö):±V#‹ð[³ö4wHÉáF€t5¸ÞŽ)dtaûäˆûWÈ (Aî"¿A”}@$;âÐ1ÙÆS@NÏ×¼Ë æ‘÷ØEÙB_žƒ°Q…äü25!ª,°ṽç8 Ãjõ\J¾bn9X§ë…p”-atÍŒÜc]ƒ3ºcxÙBÆû²9háס||Ãùb ’I ¹H‡f€`!Ø  xÿŠ€*bƒä ¢ yJ+ø$m;Ò ¡à[)ƒ ÚÀÛ :È<æ¡ÿŸÁØŒ5Ä’æ&a=I L¸UyBÄèØ½g†Ø2pŸÞadn(‰Üˆî×Ǩ(>Î"Ëy”†ãDOè€@¨ÀÉ€Bt‚uL±`Íõ1h?¥Â-Ðõ £Þ€ü/!‘ Mxp†Cµj1ñ݈øG›BUvp¡¥E>b+|ÑhA ¤x`7Co™èÒü†É7Ô1ËŽº´xòƒà0ȹlÈU4D4ò.€À0 ``cÅ $;R¬ àlïƒÉ$!Va# Ú¨TïÂØ¶LPΗ†Öd9Ãæ¸ù…ï„`´$Ñ0¼‰èTRV"«4 ·'…êB0Þñ“R ýjþ£pÃKÀè…uÄ=;ö2̃½6Ï"|!€xF6?‚@àµ@mP9xü˜k`—(+þx^ †@jLƒƒ8£€ùQ-\Dx"<]§È›_ 0)ëA[´‹@]#VÏ̩Ɩê6A¾cVPuÉ#Çÿ(þ H"ÐB¡Ò!‚näŽänAX€ñ6 ÀT…ƒÔ5 òRxH®BvF8еû†„3™aµ5nˆyŽÃý®!tâ !€L‚y˜تºE‡ -Àzk 5ÈdÄã>ûÀ܇ö:‘Ý2M0}}¶ ìé ”ˆžrF~â@^fŒ …Àl$ð'5j€ ×€rØøh"Ð.¼ 90WÝÂïô@Ôg¨;:ò>VЈ݄wÀ%IQ6ŠlSʶì|@ºF²1šq™ +àlu£|{©€ëyG4=øüC¬…:DB‡"ÛqÉI—Rø’Èü’f$Ÿ˜%_ù.ÀV >b vŽß¨0&ËAB›ŠwLVÍâÏ$>À#†2"3ñ¥J ŒÀo‚㔳k@ñ“Ǿ?}"C¥TˆG„[ #³’s¸†´dNŠ#9ù ‰IÒR­’Çl—ËdÊ©&º8êIßîOÉ6¿‘ç4ɤ’´$øÙ*æÉpLF’ht“u@6äö7(ð*ÀÙ”NNw‚Õ¯å°ï@EŽB\âm°¯¢…Ýô1üá¨QØvUÃã‚ ¢±cˆìÄJ|ÂlP'`§blz,í‘sºŒ¨cÃ1{P¸Ø¹F÷49DñÖ›H{×#÷n ‚© Hȃ°E«ò9Ó4‘‹d˜Â%*Ù,jI| Lª’k{“Ž@ûÄüE(FñEKE”FÔÒ<Úl’Sdžé%[I-úIˆnM n›“¦xžÃÅ…(waFÛÁÀðH¤. Ù­(BDܪ`©ˆ­ 0vAœ ¤0s<Ê´ßa 0»(HìÂ_éÄ(¤HESz,$m‡ Ψa‹ã$ûí€Õ“Þ48|ñÐBå¬z@ãêî È9B‚¬8˜ ¡àm) 'TÁj² Ú rñøh"Ç!.£ 6ØWÑBîúþpÔ(‡ì;$¡ñOȈ¥Duþ%9±6ŠèSªÂ©‹¯³EÎ"/ýñŒ1 ÄÀi<£bÚxåF–@<±‚E¤1ÁÀÎø<…ž&àlL@-iƒ² ààm!ƒ™àU þâX¸EÓG4þ€ž…!Þ*•‘`ú‹j¨^hà â$¸ÏY@ªæ×BÌvx· Íõ0 ?“-ê0£†…}.ï¡ç Bˆp(ƒ²aüˆ‰ŒGY¢Si^˜¡Å9ä+Xág ›_ï`aóÎ8$ÁT "@mÉ$!P!"¹ ÖÀTЂÖô; ÎÒ9šáåAíX…‹„]0$p!/Ï à R‚©'¶—Ált ç sHƒú\"ÖÁ.î 90WÝÂï^þpÔ(‡ì;!ñvOˆ˜Äuš%3q5éŠôS›"µ\–0B¿‚F:µP©­…®°0|œN ¤0s<Ê´Ú± º`HàB_lÀ@¤‚.fõ £Å.ü!K Dp.òJñüˆ‰ŒGY¢S7]¡Bw@?µû†¼3´¸iyVƒûˆ!báL KíH 0^ƒ!,Œàà‡e\>8" ù޳D¦nFà¶:3Ÿ¡µ5j yoƒûì!fe /aú IpZƒ³D1.ˆŠTG_á…B ëÐmfC›¢`ÿ ˆZHEߑ Opyôp'T‹€3Å!¶Hrpy¡ƒý®!pðáKjÔ>]¢ %9¨Õ¨4å³ € ¥€g„U 2}™` ð€hâ¾&/44 ® N t •@µTP2Ô˜˜ Ú g9>x Àä $ 9FÊüÒ&ûˆû ð@¦$B€‰ýQx"’ôªÀE{‚_Ð ˜îÉÈ&gA44 §àMd‚mu@›Üˆ(‡Dœ (QY‹,\€£à,ˆe: .€Y™‚ÎÀ`´F¤ˆ-Cj² Z@Zëæø:ຠÑØ.¡u> ­]‚ìpf »gZ2á—Ð ÄÀfKƒ3$¢€Íxn3ƒœ€ è°gk<„í€Ï…~€4 Ì €heCŒ%ÀÑ`X4wA¤ "€i ƒIÌT Ò¾˜H4ÎÁ¦¨ 8`iÃN|™àå)˜9_ËÄbÐs/ƒšDØ`ç:È9éϬ~ðt¡°àèéHØ:MÒÌ™€tå¨THàê`T:ªÁÕˆ¯`u‡ƒ­hn`ëŒ]ð:õÁ×à¿vƒù0ÏÀþÉ÷?Åþ¾ú î8 YX@/B €¶x 3ÁÐ@†ÂÌ)€X„ Œ _üp@ÑÂÀ9 ât ~Á!@AB´E ‹ä„_ˆ#¡_ĈF*‚1¸PŒ“„eÈ#1a½ÏxF‚4B£ 6j#SÁéØFÆÂ6š¶`³mü#s±ßFÿ8\ÄpŽ0q€#!’åXG19ˆ€˜È„Çp&>¡2' ’L–Bdä(°™RÊô&ZÁ3 ™ÐLÔÂfØ8P™ÏÎÜ&z3Ð ŸHM‚h6C@š&„Ñ4&ŒÁ4˜ ¥ˆM,Bi”N0š~Óð&¢¡5 ©pMK‚•ê°à¥“…-)k!Kr ] Ré—z½`¥÷…0 )„!L! aÐS‚˜¦Å0¦62)¡Lž e¸S-™ ͦ4l)£aM4 i SSBššÖ`¦³5ü)¯áM lÀSfÉHJ@²^…’ô,šÁdÖ 'xY;ÂÉÞP€²„”„,¤!e: )ÐYN‚ÊØVÀ²¶–,°¡e… ,ðYg‚Ë<[p²Û…–Ü,¶áeÐ .€YtË ^²ô…—¤,½!f 0Y€‚üØæÀ¿6ù°/Í~l ó`_›üØæÀ¿6ù°/Í~l ó`_›üØæÀ¿6ù°/Í~l ó`_›üØæÀ¿6ù°/Í~l ó`_›üØæÀ¿6ù°/Í~l ó`_›üØ°Ì †`l3A˜ ¿HeúC/ }Ëè^Ü2öá—ž ¼ðeáC/ xPË©†]L2êa—: ¹Ðe΃.Brˆ\ 2á— ¸@e»Ã-ÞnðËw†[X2ÚÁ–Ö ¶°eµƒ-¬m`ØþÇŒ6Ĺ’%Éq.& pKvÂ[„ږȵÜ%ª1-8‰hüKDÂYôÎØ–jD²¼%”Q@P ŒOôÂõ`Ÿ‹Äû2'Ôá>h‰ðìO~{s×°žªÄôŽ'œ¡<¦‰älOâx:¿xéîN'mÁ;H‰ÙN¿bu—ª`F„éž'F±:‰Ï¸Nw‚sŠšÀœ½å„')9;‰ÉNBbqÈŒ°œ_E4l)!Lž b4S"—z¸°¥¦E+Ô)XaJx R0R…“’™p¤²…$š)HŠD„R‚Y¨£ÞZ(î!GKŠ8hQ¹âj£AÅF(ÅF /lQu"‹EX˜¢¾…^(§ÑE (Q9‰µLà¢g+Ô)]JèŠVàV’‚³Ìšx¬¨dF+AXo Á„UöB¯Ntø«ŽÅ[J*ÐñVUаTUs«4U¸ªŽ…SÞ*•‘TzŠ¢¨U§É;(©Æ…M:*e!SŠ–ðT®"¥ %H©ÅHŠ*>QË TfB£ਚ…Dp*!ñQ ˆT=¢¡Ô Ø«›E\¨*ã±WЏˆUÁ"­ðn¸³Š…šÄ,ÌÁf .YWâÊBL˜²?Eœ,}c‹”XÅÅ’(¨±ň,9áa„ ,XDâÁª h°8…€Ê+þ_ΊüäWÚ¢¾qñ0¯vÅz¼+Ñ1^pŠòXW†B»çݨ®Ú…vp+­A]]ŠêˆWQ"ºpÒ¸®…tJ+ Á\ùŠçhXÞÆ×5(±©E,g1c- XÅÆ.è±qÏN.os –h\—"ä# ¸·…Ä,.‘ph‹P[ô¢ßô·xźþ-Ín)‹oX[hÚÜÒø¶rE²ü-lB `€Z÷‚×?¶Øµ¤¬&-\j¾‹TÈZ–¢Ôj¡À´ûE§D-3ái† KhZX"Ò¨”x´…¤ˆ-!!hü‹G€Z8âÑ®øx·ÃŽì-íÑoU‹zH[Ï"ÞGñp·…E»ø-Þ1nå `$ƒuü ¿¿…ül/ÕQ~_‹ïÜ_l"ú™Ð¾NÅñ|/a{¼‹ÛŒ^Æ‚õ·¨@½"Åçê/5ñy}‹É”^@"ñ„‡p¼(ÅàL.ú‘w¢‹»„]Ì‚înp»Z…Ú .Ê!v8 °”]x"ëvZ ºÊÅÕò.®uc‹ª¸]O‚êJQˆº†Óþ.žató §4_ B÷y»½Ë…î*/oÁ{X‹Ú`^Ïâöf²h½ì6/`!zô‹×@cscºÎÈÆDF0`1x‹P W`b¥#ažXĺ†$¨1Áˆ{ Aaö#s`ÃoFN0Ê¡† .\a`# kP8Â\F0‰„ Œ¼`écÎ2ˆÁ† v0Sá‚yŒh`•v" Àøkò3OñšŒÌôfKƒ1”…˜ËúÆ^2ä!–ÉŒ²Èe€c+;T`ÊqR\2†a“è œ„dÑc%Ü*0É%ÆHf2>‘ÎŒ‹¸dQC!Û ¸È>†@È2Î |f OsàÓm™t4¼¥c 'øi ƒH<; Ñž†‹–4N¡¢ hhXƒAü  Ð!Fz3ôŸ< ÷ˆg¦c<áÎÜFuè3¤QœðŒåmCãi ?ÈÙ¿ÆÌ<6RA²Œ\lIãaU ×ë½d5Þ¡®‘ qkrCZ±ÐÖHF±5|1«–Y”j¹ãU ¤PÔöƦ¼89ÁÁDŽØp cPñèßWøÄ7´ñ½7 æ4ocw²¶ˆÝ|êP7Bá¹³ ÊÜn:Ãq'‚øÛìÝÐ6å!¶Å ´4s8㘴¼@åG+(9HÉ·IÐr2c²|øãµÇì8ÏÁÆ-LqQc‰ÃGâÖ8mQØiŽ¿uÒƒ­cpêãGTô:–qÔOŽž”tÒC¥Ê'HèûÇF€:%ñпƒT!èyòˆunEÃb-lfL‹¤Vð"­YÈê:G:b9$èô¤n`$di"ËÉpH…¢Qò‰´—d@YB"^€p €à €@¬H=2*€p `°Ø¼èÀ €@€ È€K2vÀ=p@ü4&€ € @ÔX.Á€i@>€%€:H8¦Á`‹ @pX,¸€d2À `xÜœ€×q0;ˆ`r”nEA(à–0@°XÈd9À@H `xátÀ>€!ÈÀ 0X¯cÀ± \`/´ ”¤}Ñ@ö`‚ D¸$Ê ¶ý‚‡% `° Õý}IÀ%€Ð ð@zá€ÿ@‰€K`*Àh ¸Ý Ë hð5 œ2lè €“M¨((ˆ ŒF[2 hè,–R`+À8 €Ä€œÀW€.àˆ €‹R¶Àààp€9x°|ö#+A% šPOð(Ü Œ–d2@ X°XW¯Wà1 pÐKI>@°€` 2 ˆ  ˜Ûï z>€h‰l‚OÁ3 žÐQh*0tÈ}@@%€À ÐxïÕpà=à!XH Ê3â€Ó€kð8@˜ÏìÁ@ƒ`D0" ø `á‚E¨ÀW€+ÀXÈ}J`'àà "!Âð@€ÀFP&Pd Êò‘@Ô€o8@° @‰ðFx#ðš ›I ¨ÀTø+À~ K@+À8 €¦ñ€‘ Lp)h ÂX,¦Õ p€8¨°Œ!>+A ‘°J%€ ÑQ€¨ÀT`*Ô ‘ú–S€+À x|**ž V,p DqfÂáq ;`À  H<Á'€—MØ'â 0D«\ ¯W€*0í‚€K+À˜ Œ&,¢V-hŒ 6@Q·@át;`°ŠÐ$`•ðN (DP gF‚¼b@³@Y`,<à ŒÃd@>€$0À ð8NÌÀ•€M@*`ì Ü@@¬ã€sÀ= HfÐé‚€‰pG¨%€ˆ (B‚£] ¯PZ -P& Tª¼^À €èXJ¯d8@p `ý¼wÈgà7è˜ØÐè‚ Àƒ@A !t$¾ƒ‚X8€¢T`+Àâ OªèAw¶ðZ -ª ÌÈi€>€ À è¼ Âú‰€K(xà ¸@Q»@ë€xð>€@h]J‚*A! “@IÀ%€h 8‚¶g@µ@[@.´p ¸²‚ÕjÀ¼ að2Hèô"–W€0@ÐIXE¯]À2˜ÌLNÖô „DÀ#Lø `±nÁ8€ àRH*” gÜïw »€]À-X¨ « ˜€$ÐÀ (x ˜€á| DP%L ðÜ©å`và>pŒh~W‚?%`—N '\P mR½Áj€»€`x0p8 ÜîuÀ¿°cø3 È çK€¯YÀ2pÂ.9¯]1( ”hæ AÀ‰€G°$ÜÜ Á÷‚ŠP@¬0WÀ-P* ÀÆð`à.àp H9œ€ÎÀj@ $@/Âá{`?0"hÀ .x÷Ô`qÐ>€ Ð0·~]; ž Q@)˜ ðªÙÁw¾°`à2 €!‚üÁwÂe˜3Ž H~ƒPd`8@ °Ð6&,¢€W€.à Hý» ÀK%üè (§Á\`±0[H.à 2@%A™ Ìd0t ?nƒKA©× j@5 ¦ÏÂö}@"`œ `»o@Èj@8@°ôÊ~[A8ࢀT`*à@ gÂòAƒ€Åd3XÈ är9ÁÀc3 ˆÖƒkºè@|CÐ%&À–K(  @)QÂí€}D$À è)‚¶Am ½^00(š d<£àÔ€j@5 Ê ¼<ƒœ€Ñðjè6È ŠÅ+B;AÖ㋘:º{–}‘]@‚@DÀ"ˆÀ `Š^³À_P3HÜØ×*5Á+Àž`S+ØÄ …."›ÀÒ°k62 £̓X©Î@d2¦ ä¤kËàô …ˆGÈ&ªF>lÜ<€­V9lüi n¼â8Ìäj»_M5×Õi 0 @°„E­ÀW€.Р îÝ­ô ŽàK'ø" à Aœ€Ïðl6°Þ„¹@ÚÀjH3˜ €_9œ€×ÀrØ?Ð#Zò d q«¥Bø¥íéovOcOÃ4Ãl!ÂH]Æ&eR’^• Qø@ÅÐ `ÛŠU@¯[ð/h H°ó@PK(8 7ÙƒÁ¤Ô€n8t¬t:ÂÀÝðj¨3 WKƒ9œ€ÔðqÀ?x#¬# rô’*£µù¡ò9XN !ÅÉâF ì¸C„dÊ0z›pÇlBÜ4x‘¼O.!¥x-€¢€RP+Àh ¸@Nº€æ w€?°"è: Zô¤g »pb4| ÖÁØÀí€vÀ9Ô ¨y ‹@Êg 3”ú–€BdÁ@1QÒŸüÎlCB!t L¥œ±Ð}„B,$'ô >£â–ãöcR™_ª=  ‹Dà"<ñ˜‡è;%æs‡ €¢€W€,hp <OTÀî }A¸$n Ó£^¶°`à3, ¬*ƒ¼éôpyà;`è Ìš' Í@g 4Ì„* щ0ÂôA[ žHQì Žxë{Èj 7 j @‚;Á&™€SÈ*0  TìƒAœ€Õàp€;Ô. Žèç€ìp€5„Ø žƒRF`Z0.à æ¤„ãA „E¨#ôÀ ²'‚©]àµ@]È0t öÑŽÁá ý }=<¾YÖR»€a2 ê9Æ‚  ÀK&À |s‚Âl`»°`à2È EÖƒ—ÛñPx¨;`¤@E°€ávÀ>h ´0üÆqE@©W€-PP ñƒ œ€Ô€l˜7ÔÀ{]¡€ðà} A "`ü |ãŒ] ²]8.ð– |hƒM©ÚÀoØ8@ètb‚X;@¢€R¨+Lú ¡Á‘Ïpjð7XX ;ࢀT`+|¨ Ń(Á›ÀÒk8<46T`¯Z .àö ärRµ€Þ0p€9Lè >¶ïŒ`Î@h64z,ƒŸAÙເ`¨2Äf H΀çÀvÀ;`j œÖ„ÆÀç@vÀ;är ´„Î`ìÀwè<ð¦L%ƒ¨Áâ óÀ{Ø>€¦ö¢ƒäöá@|>€ Q„€‘ì²€Ûæ¢¼ýÇÍ=¹ÎŽ*oÓwHÍFM1ñÌ{Ÿ ¢—عe¬,±c‹Y»]?yÔ+9MÊ*OÒw“¸žÅ )4¯ç•N;\çää%‰"ÚEÒ+‘p¤…%95ƒ ÈÑÊŽvtίÅËHj@¡ôTyƒÍÐü C‚4„œlThÓz]€úHIÆ6Rs¥¦=|‡Š9a¸`icIÙG:qê,‰$Ž&ÑKË^Ã*›èÁBR6’æ¡ea-݆Œün{ªŸ'8ÁÊ2t´ÈËF .qj‹8Z‚äðȘ7ñÝôˆ¤–'iRËbaãIœ<òhE’TêªE­°y-½tóâa)Hβš£ ˆ¨Å&¡/‰€M‚ƒ³ú3Qºè€ä[%±EË_3›˜í§üD¢M¼©¥°A›í¸tÛã! ÙONüWÂp‰Ä ûüBB0°¡Et/aœŽzd*$A; °\³"› êGäCúH“œ¨U¡°-›Í»u#æ!-[ˆô@ÁÙ ¸h, Õ=BP Å†0‘ªŽ¤€dc&YN‹`bÓYœüú¨sHÒrU´V³¡¹µ}d,#-±%9!˜ €T„ð¦”0᱆D¬)‘q Èqä"A,ŠHYÓš”æÇÎC‚FSš¨•§°ŸMàv{ó!¥\3c ¸Eöð{4%ÁW (nCè#A<‹bãoq IDQbȘTÔ'4>‚F…M-‘†íoû½é†Ð.A;X9Š ðTøá ˜Y4q ‰„UãøðHRI’ˆ<ÂÆ¤9Ùö‘“DöªÉp,YiÛŠ^Eˆœ¸3ÁYð:Á„ CÈ :B. Á‡@¢O½†¨;‚’X¢‘0Ù«NŒ~”K%%A Ñ]ÚÊ凪Á€H¡å ˆRB `U  \ÈÁ Àk'!s ~ˆ)awB@¨¼¦;Â’”¤¥¬1éµNì‚i¦AJË&`9›¬í'ìøZ‚[€d„Ða‚L  OØ @fð*ÈÀÁJBÊù‰ SBøèòHzK‚—ËFõ<ÒR›õE-y‡Í(pëÇ SA;4AL1A$€$È !@ ÀœÐI‚ø!) @kCô$ÁS mÃÝ"¡4в^s?|øèxI¢~U޹öBµÉÍÏr„(‰v‰<àk8 @:P €@L`$Á‚P—…À6âà®68aüÌž¥~0‰ªÎž´Y%ÁGK _[5ìwéC¨;Á} H8AJ0&¸@X:&¼ÇèN‚ü ‰ÄZ#7)‰0QâÕ™Ü'ˆAÂ<Ón¨E®°ý¥Î&yd"¶@¥ð@„À €:ЀÀ €ì i„,)A‘ðŒ…/­,ˆ¤Æ*yxLöqÓä¡ý'ªVÂí™:ÙG¾n1Õ ¨H² À5À(@ð€è @p8Â<ÕèJB°°áòGb}– æ¼;"Ñš™/,Ùƒ oóÀ )-ÎT)áð!€´`,@8R@3‚@ ù ¸_C’!Ñ< hhƒ¶!y+Êr\£1œö(gI*{•~¹ÖAµÝÎÏ€„ÄnåÙBК¨€yx À2 €  €ð Pl„P*Á x‘ÅJ0±¼¸dñ+é… bu”£ 0ÊSY[™ôß7|À"$òQœU )§WéïR¥µÜ HA¶ 8,àp@p  Žð=‚j°ätOÛ(íˆ`K0̧=ª’NŸa®‘ {sÓá¡99zNN†ôݬ]Ž-Õ*٥ϲ’U;¯=¦.Ž@‹TÀqp À@` €\€9°T ðx5ùˆ¬F.8Qý‘äŸÅŒ1°NÒ”j&]L‹>aCœ ðÈDò:2i˜$èè‘O ÍÙ"Þ—¨ŒŒ‰åƒ5ÚÒšªüµ=Ö°Œ ¯PÀ¢¸€zÀ€À5hÁ4 À‚…1¡Üˆ£…ä5Áç‘$™eU/9 ŽL}$C¥B*ã^*›>é÷ÕC<óåê Zû.\*øX{ɶ~¤‡-¹¾Pn—õh°•°ní‚Ütf§M¡³ F¾ ÐB €<˜ @p38Àö  ^ƒŒ!9‹Lgcª! ( L[S%›¬òhEHq(¶Æ(´ýÇOA‚”\¥A3éíQò¤µÍ³Õ˯ʼnì­hs\»®x|™¦: !Sޱ–9·=çp«‘éj[kÜ- à[BRð_‚` bŒÐ1‚Àì H[Cn q/ ðd#  X£äëÈ F`”˜²&3­»î`w Ù_݇80!?@6h `?¼  `0!Ah ’…œ5áý«F7‘ôŒDá+A~M sí¢5)J ÐÃÒ𯄤€ØÐ)A*°C‚HÀñ XZÃ`Á&Š˜`Ãlщ–TòîÀá§´˜„`ÄP%P5A cƒ|!!= ÈnÄ%1TŒmÓ")/Š~\s,‹°Qâ<°nƒàž„Œ"A PFjʇHBâc¨Ã†Þ=b"è§¾ˆ}ÃŒðÀ…¨+X ]( üàOâÍßÇÆDâ`ìB!ìxoCfPà‡h?Â.0ªâ4!ÍìŒDÑ ‹8!qˆ¸Ibr·†F6ááx$혢)!S ^$êîDâVŒ `ˆÊF˜7‘ØÀ‡$‹'(âG 8±ÎÜ{¤"9"‰¬R² x†„R#Ù+‰ÔS¿̘×'ÉI ²Y‚ñp­…†-YvL$eC ˜Èfj4á¶ Þpóœ´üèGðĹæÔÛ[ƒ7g,õ 0V˜scO?-E®¶–êâ\˲äßJI©C*e€³BÄX‹1l.æÊszur E 4(¥\´—à i Åͼgåâdy•\wê?HA$äì¤B|O ñD)Ålµ—Ó&jŽ!à?Èu&ªV‚÷cí%¹¹ç”ý¡$RÂoŒ±–3FÛãØ„‘òDFˆ±#¤˜™”"ªZŒœ6çTú¡dp— §YëÝ´¶ìèž{ý…QfDKb*Å@¨bÀ\ŒQ¦8ÇpïÃÀ{òFÉqC+eÐÈãœ{Њ5KJT-öÉZƒ|u/^Ã8Ç$æ ¡âÈÑ:+…üÒ“à† kR«v±¦Ý3Õ€ÐÚ4I©™?Àà  `ÀÐ!…PÒĸ°ƒ¤ƒ’r’ZÌyµ;h ¥Düª–³f yÆ»ÇÛbt€–S–ŒT°$€(€°&AP: a|:±H/Æàù#ä­—óFrO‚H)©J¬ÚÆšCwtÏVChÑ&¦dÿ¦U˜€`@ ‚plØpÂx\ 1àC‰qO.&TÝŒʃUËiƒ³FÄä^ñ„1JBKiÓG*}i°vr¯W‹#k˜ à`Àè*!(.‡!'…¸Ñ„$“”rÒbÍyÔ?h‰%§E<²—³#j ý×=Ø£„¢š”UJÛaí »º´Â¤Ö:ûeí…˼ XЀ˜ È …0Ì„x¥ƒPw’LQ !…50ø¡„~š’¼] Q ¶÷:ó_ì-‹Ò>`ÏJIêZ®v6Óܹ}¨%¦õFµX;=mî•íÀøˆ 2Àø& ø'ê"„ø´x{òRQ‹!„4§ ö!p—ÔB²[¬!š6' ïŸt‰ÑþXÎ:+R+ {²¶¾äÞ;ý†1–M¤õ¬×;iî Û¾¸?dL¾ ÁX)@¸ƒðšƒˆâÔe ÁÞAÑ2)… ÃcŽzr3KJ U-EþÊÚ»„vO†Dã(¦§JµØ[?nn•íÀø‡ålã¢äÝ1©U޾Ù{crï-ÿÃ8Ó'f§ø<¡#…¼Ä œãDt‚F YA+ÈÆš³–{r2K ùS,õðÈÚ{{u/^ÃXËd¬®˜óà+0¦BØeBK ñ˜;i$ÄÈ¡BÐ_ÌÉ´:GÅ "4j–Sò¥Y‹Õ´–êè‘0l a´9‡±%…PÁ£ô”ŽT ák/†DÔ#º~Ò:KªS,ÅèÇD@†0J áX/† í!D¨¤ÒÔ]Œ“4Æèé´‰"dPê­h AJ*p¸ƒTtò2MJ‰j/Æ4γxsÏ)ýBèÉ(&õ ¬Æ˜ß£ü‰’¢ˆW‹¹Ž4&Èá3Ì~‚)Hi}>©Â0J‰ùV-ÆÏ3ŒvOQýB(™¥dâ£J±k0FdØc¶{ Eõ)¦µ§ÌÁ®8‡h÷ D0‹UMJMc¶|P2Eé,&Õ¦U‰õAH}$„ºœ”:œVk)¤äÆÔb¢Vë5r&´þ¥B½Zk¥©Õb±–Úð`Ìqh®UôÃÙ#:cl½¢5¦ÌÞÝ +èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£ *€Ø£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>ŽØn >£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èÞ‡€ X2f³@£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£è»² ÈÏ­>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£è§€ ÒУèú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èí¡Êópú>£èú>£èú>£èú>£èú>£èú>£èú>Ãfú>£èú>£èú>ˆëèú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>  ¨…¾••%š] Íjo5u¥}}>MBÕHµPÍZeoàŸòíÕÝ¥"+¥6­C—¦7¹·ÌÿßÌâ,å$êÄò û5½µ"U2Çg?|G‘¥7¹/ÌŒ²$´œ¸üÀ,ÉlÔ„áÔñ­í'Ç#§:/PWe÷{gO¤ÿ¹‚T†<Œ„•„ ä­ô½|Îüâ ö5 # ;FÁ¶Ú~ò¯ o!Ï8×OWe{‡¥ î,æK>h¶…¶¢6½ÆØæó' ÿ&>¯V—mû>s8‹73:{B;Nc^cr‹‰Ó£ûÀË߃ÿô",Dìȟı„Õ¬úUBEe•ˆ}ªÌ5íF V-&Kæj‡n¤>ÀVÛŽöG/)§B7Zc"þJúBû‹» Ã1+I;d[‚{¢ËÅcé,3ìY¼€T¦ôÌüóEý> bu†U©mÌí®Ž.®N>lžŠŽ§–ÃÆßvú'_-ÏF²ÐšÃê¼Ò»b¿ºÉ²Ùí;Ë"#A«d ˆs®CÕ;ýD%ÔNÒK‚^òxŠ–²¹Jß;Û2S^ ŠÛ·ÛåDL?dk„—LÂ,ìm¥=ÅdÍŠí°mÔe÷¾Þ;[Fz¦™>¶®Ó†ïO —$Ï>’†š`J>Š! yüÉö÷Ú²ê.‚MÊqê™êÅò kPïÃß”„=¬m¼›ìÈœôMÝHMp]—E½-áÆ~(I¦iö‰f§ÞÅ–â^þ/G3gM&ñøÍi§±‰Éukán9|©”é¶IÞ¢ ê%gÅ·-Ýž$ÞGhFˆ.§fÅVâ–þ§/4§Ny]a"xë`¼ˆœà“À¤hÉèüY5AqɯÁî¢-òlB©Úæ;!“[ÔË\ 4äg\˜<Çœõ=!åLµuíž=Åêv¶1ÞSÆtn”N³ÐÞí¿ §$ç?X©!Pàh£mÐMR{³°ò±4IvÙ¹Aû<{âºZ÷ƒ3³m³¦ÓݤPWŠÀÉ LñéÒ²ŠUJ”âÓ ÃK+…#½ó´(¤[Äl½lëÕåD=n–µ½Õã¶~+ÞMîo&N®>ÌNéW‡ ÿ;_UOn?z—†÷’ןª—µÿhGtÏ'7™_¥°»i0ÏX¤ŠP‹Ð¦ÐÓá 1EÙ„!â²AÚ€b½Êú“5snó§+ÞÜF„xŒ¨Ô×½1[}„Ŭ-Òµ÷Ö–>†_æ€^Ÿþ¾^ÛæøW/IU÷bo{7‡¿“ߟŸ«µÇÀ×P\ÏiWu‚/ŽOš¥Ç°Ÿ»¿Æ¯Ñ™°õ˜ÚÐÐÚ`öaùPq‡À™ûÒ8t*¯Úêã$Ó]»•«ËÜÔ4tfœ—<Æ$óÍíJÍt%œÂÕè~ ¾/žQ–rž’>±.Îþì#'=ŸWp|ŸˆŸ”O «w¶wÁ¿Ì¿×âW^_j¯wWƒ/š×¦7±‡¼ÏÇ×Ò¿Ýè1lYF*Yá )™Ek1˜iʪ27òoò©á»#Rˆ“¾òœ%„Wœ‡´¶Ôä}õ;ÕeE­´…Ú=þž"DNev…¶¤žÂîàüwï2wL_eŸrG~‰ß•Ï¡7¬§¸ÃÎ'Øßã‡î7ø‡o`myo…gÇœw§ÿ³7¾‡É‡Ô_ß'é¿ôþ–y¹gI`¡eñw’ɶaàÚJAŠtúªZà ûKƒ€‹µèD\K¬{œªT×Õõ.X}€µ§ÕÍ•òF®86Yvy¾™>·nÔþñnÿ ?§(BäAÇñ³ù¨É§Ñ±QÄ ßJú(²TZ‚ê³jåk;K~ °[â,|C|rÄ ŒÍ´ùå$%M=uuœÂ=ç& ®-N¦o z9ÿ™òQìÉïáûjb)ÊJ:o˜:Ãêñ› ÛPƒ€ë± àÌ4>Ìm$šTÆDñ•eDel]“¸­Ý^ `ÂJ²:ê2R1R7ŠD¢X²rú‘ªµÛ£C/c[È›¶CãÄl>DjÜ–ÜÁÜì%m=Íe=‹…±“êƒ:x2s‚uZ}ŠŒZ ª¹º×jùC›l+•ãÀ[ë4\A´l\–¬À¤é¥9¥`M†2´Ò¹2ÂêÒæ‚þó+:ã]C›§›Ï#÷$¤HŒqlš Â4êM7Ý]«“k*+Aû\ã{S›‹½ëáô ,ÄS,yü |Ç$í==8ƒX kû‚ëœó¹3ØCøÄ„=taL…¤ª,δóM;³«kÁËÚkõÔä1ŒQ¬rt”|¶ÔÙLü »é þT40K”h¤†Ü¦\Æ4æuE(D$d8ÜO”h<‚|ܺäØDöm54,q$†Üžœ·lÑ”ìŵ%=BL§¤¼œÒôê¥]í7]R´ÛôïÝ­35K•d½e!]5Jýax½Qd…xÍŽ‘}¤ÕÏXÉL±ç–Òz\z èf-ä…àD¬+rØP]_‹õ‘‡°E¸¨ÀȪxïÑà\²Kã …Ý1â(®=£ Tf:TŠ×ef-öEç¤ÁïÙÃ.$h ‘Hº+òEÔÈÅã£bâ–pU™‹ ild.åFÌÅý_S?:j9ÍŽ¢&HE,ˆ±—£äi¾QÊÙQf+£¢Ðºôc.e)Œ÷9¨¶6DæìáâœÀ$>ôˆÄ3Ê)·E›(¿%O#U$oÀŽ–å¡KÝ+ å’(¸W—Ès&dÑŒñ¨„6MÆïìâÚ3«€wa&Yë¹>H‡â ÿ) =tƒ€Ð•‚"Ckˆ}e"kT2‹WƒB3jFƈ㉸#ÝÔ€\QkÊ—9_í-›¥æDÂô:–jM–‰¼ç8Í=ÄëõÿÏ{®«¹ûË@8H\¡ô-†¼Ðùš#1DÞèªû#ähŠÌϪ<žGä)9!ç$`B}€S3ŠÖ¹h“.ÄF hÈÆSPBlØ ïqÇô:,§itñ[©³ä~9ûb‰AhˆB± á!¨T>ˆÑÑ9ú+EÔÈÈž#„äv\z2BþH«é$àm²‹ÖU6‹ÉrV0f9Í´Sg¼oËNN9Ó¶;¢'—öúY#ùn€ÙMj~Bžèhuv"6„ONŠéQ{22üFËHæ5G#ö4„"‘)R8ºIhIsÉ6´žý”â’¼4[yKêAŒ3H¦ŸÚLœÓ—Œu“ÏÁéA>8æm{ |ôR…ÌÊËDsè -#Ôh(æQ×b>H ‰9#;¤T–¬“eÒ}âQÆJwDŽDšneB¯`Z6‹Ì‰‰´3"枤گœ#óœZvQO¹í>¾ø1Ï É4&&†Dõz#àEè´Å°#V4r("þZBÝH¸I!Ù%‡¤×ÄŸ¤”R ’V Jýä_ •!ÑB "X¶ ©1†®2ô&ÜÛ(As¡¶w-š§ätþ¨ T ‚P^ªéB=†` ùJ&vEÿPðÜ%a|Ïvœ¾cÝì‚kPòê._Ga %&Ü%N4µž—ú“"Zh(Ms‰ºa8¨§:4ë¦ô“ÍR{FO™‰ø™?¸( 5Ž µZ„²P²jeC‰¨|åü¢HÔNŠQ ÑÁ–PC \¡ñÆRìLÕAמ@@ˆ}é0¤6ž–Rü:eSMI ¹ñ9'SDﺞ“ã"~BOÿ*ÑAo¨AÕ ¬¡™;ˆGQ# 'ET¨µå£%ÔiŠºQÇ*:ñGš¨ú5 " sÂd4„/¬È¬ò„CÚùÒ”’_M ¼Y:&§ˆtøNŸÀ” òƒ„P­ŠõD.¨š~¢ôTeò‰QÉ*<GÚ)…!¢¤UTŽš’LRWJLIÀ)=…(`¥"¦¢•'R­*V•Jö€ô C±g>Eëi|}9§Ð5 ¡ä”TšŒÙQÙªA!H¸©&…&È¥ T¥ú•^R¼êYAK^©re/¥õ”Àº˜_SŠc¡LŠ)•3¦lÔÏ*šSFJiaM?©ªµ5˜¦»TØ›#Sh”ÿ™åQ”©PvÊ4Ö·ÁkVëjÅ V窲RƪU6R¥ôT§ê’iRª:åF–¨»UŠ¢oTE ‡ñPêªEBú¨X• ’¡6T$ „PwªEA¦¨2’ ­Tª‚qPKªÅA ¨ UÚ {TjŒ}QŠ*0åFBá'¢ ÊtroÄɶò²Tåþpº5–ÖòÐÃY7ëÕ_í+ÈsB­ÑUªº³šVCêíWÙ*ëU[¾«Ebr«©UcJªUª™¥Rnª5Cº¨TúêžYS¤ªpuM ©§•3j¦6TÁJ—yRç*[…KZ©g,2¥vUª¢ T3*…PjªU@§è™à2§^9BGW—ߟFc$ras+çvj..¥¶µ4V}ËUXõKa`ú«øÕzü®í•Ðz¸šVêªØ‰Z‚+A5fX¬••Œ‚°æV*¾qW†ªèõ\,«fiR¬ÌU*°IUÚ*¸…VĪÐUXÒªùUZjªÉUHª§Tž«˜ÕqŠ®UºŠ¶¡VÁ*ÕeZT«@ÕfꬱU‘R`Ž6áC~góüî÷Ü2‹\g„l ˆÈ0/åï^»—×6:à}[aKZ9i:¬ðe—þ²NÖ6úĹXWK!_¶+ßy:®ÚUÒ ¹3WJÝU[B«[õj­Õ‚³VQªÈ X¿«Åa2¬Õ‚¯ÿUùª¾YW²ªóE^«·u‚³ŸVm Ì™Yu+*…d⬎•ò±ÇV2 ÅyX–«Éy΢œÙ|R®Î¡Å¶~–—ºÍh™ƒÓaëûi{(.ôÒ&¸íVøòÚôZëëPqh˜¬ê5˜x²ˆ–ArÆUX—ë å`ç,U~¢¯Šé2¼/Whjé\Ë+ÅpL­ÜU¶’¶8V¾ Ö¥Z±+Ri¼­'¢¢´V|*ΕY·+3Åf ®ÏUÈ’¸ÆW Êà…[ì«xnt­¼ÕµŠ¶oVŪ׭Z׫W%jmXbB´#M}¯Oµ×8¸ÌߨÕÌšK1‰dbl[å†E°;õø,½^—|šêx\¼ ‡o-­•¯ÆµJV•bÐkYÊ+1µeR¬åŽü±„Ö%úÃ{XJë)`«ôµ}°¯™Uﺽ‰W–q  &7ÂÛ¨âú×PKªËqÏ­Õù¯Å4Íöy"˱Û^a茩€3/¤5ér»õWZòçl\wk‚ o~­Ø%µp¶Ö®šÓ¹Z7K?]g¬È••ú¹%ây5ƒ(Oñ=ï¼-—Pdãé›Íófj—íéœ+2ËVDºÆYXŠ£ )`yKø|q¯BUßà»×D"åL\H ~ny­ª%°ÙIáÔ¬"f(¯¾Yë»×L:ä&çÛk!kim4Y 6³R–V2È‹Ыßa‰,ဈ/Ä%íײì‡]*«™¦;–¨&ÿ_++Îèw&.’È›·ùFÞŠØ#ZšSG;g‹ìʱ”â²ö5<Řp³˜`sËûí}h¯mõæ¨ü€ÞêCÉ v´ÎŒáÈã86å<Ù?šÄcMhUÌäõ˜I2Œ&CÆÀX¨+kaMlµ€´Ò)Z9^fṞ Ï¥¹,7 ¨Þ䇋fìk³Sm¦\´PV{ÊÍÏœôƒ’äpô ô¹}¶˜¦Á:ÖZ‚KHÜh@ŽK¥Ä5·æ¶é¾ÚöÛ‹[/js1É}8VÿÝžÛnÓe­k½-Z5Éw¸˜7 Ýø}gÍl .KÑÄþ8&ò^ÜQN ŠupHMé]¹e8/&öÊ߀` 0+€$V˜€`6D ´+€$V…@ý}د¸à à1$ÀlˆPô¯¿Õ÷º¾î×ÜЛ@¸AE`Tÿ€§_‰kð¥~¯¾u÷޾é(àð˜€`6D(úàl€]~;¯ÅUøj¿×ßšûÑ_vmJà €!Pþz@˜½4àD½€Ðn €°¯Æø~¿×ßêûÝ_w@pxL@ 0"{€ÀÈ6@pôQ p!Èn `j'Àxy H!À6ëñÝ~%¯Â•ø¾ù×Þ02 ÀhWH ”€Æs@ ¸¡1€ز€ðrHÀh÷àD]€  (!p]àÜ€_Œ+ðý~ ¯¿5÷¢¾ì*@žFFhà°p€ `–0 ¬ª€@\Fì€X ðÀR€° Zük_‰kð¥~¯¾u÷ŒW€)›@ˆ;D <ü€0šmÀ Œ.À€¥@FC@¸á ìR€ @üÀG „WãºüU_†«ðM}ù¯½ G'€¸‘€€@€¸ì Xe€ k* ü”€€;°ÀhD€0º@à&À¿Wáúü_«ïu}ÝX  ¼L€(0Δ@Ø%Aàäñ€Ðnh@ `v,(šà=ÀË ”G€àÐ1`.¿×âªü)_+ï}ãZ èR(àä—00C@÷€„k °-`TŸ€&?@`Ö¨M@æ@h7À@Wã ü?_ƒëïõ}î[` W€)™Àˆ;D <ü€0šmÀ Œ.À€¥@<Bá`ÔO€ðòB€l×ãZüK_…+ð%}ó¯¼` ˜h+ H£€À\HÀÀ @Üv¬2Àµ€P~J@˜ýàX`  4!p]àÜ_Œ+ðÕ~ ¯¿5÷ ƒ€/¶±@x™P` ´(€#°JƒÀÈã9 ÜЀÀìX P4#À y À–-@ø  ) XÀ-~5¯ÄµøR¿Wß:ûÆË@¸ü\À @]*@žFFhà°p€ `–0 ¬ª€ðRDÀèçÀU @€èGà„ üU_†«ðM}ù¯½÷`œ2 ½€ØÅUà dA€&ЮŽÀ(? Œæ€pBc °`)@Ѐä7Xµà<<€0¤`µøÖ¿×áJûý_{«îí}Íe  \€€.° ®€ ŽO ˆ&#4pØ8@°ËÖU@ ø)"`ôs€ `€*€ „ Àt#€pB~*¯ÃUø&¾ü×ÞŠû°È€`ö\ W€)›@¸AD <ü€0šmÀ Œ.À€¥@<Bá`ÔO€ðòÀ<€l×ãZüK_…+ïõ}µ÷4‹€0Öµ@ø¤QÀ à1$Àlˆ î;Ö`ZÀ ¨?% L~€p¬0Pš€¸.€pn@€¯ÅUøj¿×ßšûÑ_v+î8 ^À €e+@2 ÀhWH ¬ €Æs@ ¸¡1€ذ hG€@ò ,Z€ ð@@R@° €Zük_‰kð¥}þ¯½Õ÷v¾æ×ÛÀºÀ¨¿U 8<& ˜€ =À`áÀ,`@ XU'उ€ÐØ5€ª@7ÐŽ Àøª¿ Wàšûó_z+îÅ}ǯ¶õö˜{.”­ðƒM  \ €"°*ÀHÍ6à„Æ`ÀR€  ! Üp€ °j)@xy H!À6kñ­~%¯Â•ø¾÷WÝÚû›_p«í}¡]` T_€*&žLFÀ€@¼r `–0 ¬ª€ðRFìÀX  ÀèMà˜ üa_†«ðM}ù¯½÷b¾ã×ÛzûM_hkìÝ}¯´Õön¾ËWذì¸P´SÀ 9%p‚ŠÀ¨ÿ= LÞ€p"]€ O' Œ†€pÂ2ÀØ¥àø4 „ Ø ¯Æµø–¿ WàJûç_xëî•}¯¶5öš¾Ð×Ùºû!_bëì}·¯µ•öš¾Í×Ùjû_akìëZ  üT€)0ú™À`6D(úàl€ à†.h¢à0@€`ÖÀÀM@æ@h7ÀXWã ü?_ƒëïÍ}读÷¾áWÛzûc_k+í }›¯²ö.¾Â×תû_o+í½}¬¯´Õön¾ËWÙ û _`+ëÕ}o\ (Z)àœ€àAE`Tÿ€¦o@ 8‘/`”§€FC@¸á ìR€ðüÀB l×ãºüK_…+ð%}ó¯¼u÷J¾áWÛûY_hkìÝ}¯±uö¾½W×Zúß_Z«íå}·¯µ•öš¾Ð×Ùjû!_bëì}z¯®µõª¾².°ª¯ÀH“O  œ(€#°@‚€ Þ9ÈÎ`àV€ .#v ÀŒ,Љ`Œ&€ÀL€-~0¯Ãõø>¾ÿWÞêû»_skíå}±¯µ•ö†¾Í×Ùjû_akì}u¯­õõª¾¯×Õšûç_p«í½}±¯´Õö†¾Í×Ù û_`+ëÕ}u¯­Uõ’¾¯×Õ̲€ žQ È.$``†€øé:`ôÓ€öY@ x9$`4~€p¢.ÀP”À¸,pb@]~;¯ÅUøj¿Wßêûç_{«ï}Ò^ l_€*&Ÿ@8QG`”€@¼r œ0ÀÀ­@\G€@ò€Dc P>"@Èc @ð`¬¹€€ºSÀ 9%ÀŒŒÐ=À`áp"^À (U'उ€ÐÎ4@ª€7Ðâ¶À(¯R` ô3€%v‰@xù<`4Û€]€ J&€x„ Â2À¨Ÿà ˜h+ H£€\HÀÀ @Üv¬2Àµ€P~J@˜ý€X`  2 ÀhQG`”€Æs@ ¸¡1€ذ hG€h÷ ,1$À`†€ î;Ö`ZÀ ¨D%À`À‚ŠÀ¨ÿ= 4Û€p"^À (O' Œ†€p@‚€ Þ9ÈÎ`àV€ .#Tÿ€¦o@ 8‘/`”§€R‚€ Þ9ÈÎ`àV€ P4= LÞ€p,`@ XU'àŒæ€pBc °`)@`áÀ,`@ XU9 ÜЀÀöY@ `œ0ÀÀÈ€°ì º´,â•‹j‰Á'©ü*.~’ 5(²޸¦6/gc i1¢¾šÈ¨ØV(‡Û‰¹¢¾8'$¼0bq ¢—âËG0«˜&)$‰ÚY‚[Ãè*G@ &†‚o •Í(ÅÐ/# dº·(§/z'ø‰ŒL"Gr‹92 œ‚£¦¡ß&Îè Lº‚:Æ#*)HÂ>.† øB¨5P¢JX&¯Ê 7Eb1§…¤Ëøâ$à°Zð*)6 [‚i- “§Ø#RDtŒnúBøñXµ¢Æ+Kö O‚s縕6ò#mh½Áþ±Py&ì»°†ÏøàË”h0ƒ´ Áõ ¨O(&: ”œ‚IB ‹¾@!WÜözŒÁ £ X¹­ ,* ~;‚}\(—P#Æ"ˆwÂâçÈyI@¯ã†Ç횥pa’úŸoÌaIq@Mü8{kan ðè?À÷DƒDà×êø3L 1æo€°}H)ú ýÁ`S@Öà"wf5Çô€ w9hÑÃø1öë â)bÑꨫ †(xÖ‰ÛbBHȈyb /¿•ëaÉÚhkäRqzáj;xUqô)¤„Ãa ¸DìòηæšX6Ò î냋àºà,R uë{j`–½x#Æ"~¼‚ z“¸êB¤Mc`FX͆60ÀÛ ‹†ÂºaX¤¼è&Îç "Y¢%ÚX.Zå‡!>A¬Ñxd³@«¥…ü!NΈN΂‹‚„]ñáuÀ>ؤ¨t—ÀÐÏX1Q² §°‚À…³'m° S*‚4šà…’ð¢ {ÅÀkIÐe®„ óãO`€È¡/\¨‹'¿‚Ÿlˆ$ô°¨ ‚½@yV c·¤…Açà],ZÏI…aÁ2¤ÀGê°Þ[ƒöi`îPx8 +ª`ºÐà,H ^P‚pô`“R"³z/Wî tŠÀyÔy›†Ì@[ÿð±@6Ã_ íOC Pضñ„*Ù)Š1"V«H‹›æ „“<Áïi-&…µ‰!Tµ(O‡ Í„UåáoÈ<¯\4ƒSU@Ç}@.Á ÷¼‚’{€šð$Fâ„ÿÄx)¸6¨Ÿ(Å€]WHä¾"H3êàH˜ðJÜ8ÌÊ_’c#t¨»ã„+ÒŠ2Sb^a`Œ®Ž œ‡ßaÀ gÑzm”‹aKt8Lúºáþ„(Ö@÷³¸9³v oªƒ!û»&°+¯¾ 3faeàŽ[¸!BhÆ3Ñ`l¡(abëüb @R‹ˆ>®zé œ =õˆúš&;#v äWC?| Á§Î,ò­ŠhÆbgÚø ®Y†æ!»´Xf$R‰P…lÙ!@†(J pôˆÀê~6LH –ñ‚ëˆ ­‰ø(LÚ [À,j¨ûlŸ4À`lèa4/(3¦@G%HvJÊöß²@3]I…n=×xŽ|õc`‹ÈiL.B}Ф Bpã@@ º&{]¡µš8d àæ<…>ûa3·hF—¨8ƒº™ Û›2“ §°‚°A@ž¸@$¡tó² sUÀšª"³j Sj°-„gš ;$ˆ ‚ú²¢ (LØ ¸E(ºFÏãÎ-¨â5ø4.y‹øl‚»¸¨Ÿ[T$&±ˆ2JÁÛŽ@kÆFr!…‹láB«xIWv³qÐ`Þ°À2Ø: £f©H›çH#´ø.Eß”@mÖ !½ÚOÐL“Ào2õàå˜à3æ˜ ªèœh”Üà ì˜5\/“Ii$“cAО@b¶å£kÇgÎ-&- ,±‚Id`ƒKLoT{C°UB¾1΄Ri@ùÙ8i Æ&‚ãÀà§Å°& ~ŸþôÄÀq†H·8ÓOQ'`L&>Øè€Üz@1  á6dž…× æ +JJsCRà Fè{&UoÎy×dÞ°Ù%ÖD”«ÔŒÃ)8Ñ.æ¤ qäâQ€ƒB¸݆l»l-PPÚû¾„#àäþ`36¤ t1‘$ “/° ý¾d‘§Ê^®˜V³Æ j ;$ˆ <×j€¶À!î1}ò€MÈÀIàÙ{b*€„J÷Z.§4EsÒQM; NËIir$>\˜÷ X7[¸ŒD™B°ìè–<¼ ª»¡‹}àV?òß2!S èX°3)Ä Cé‚|8`Œ6höxÒ§€ T}XÚ €ß²@0 5Œ%Qq0€Ì€qBÑ6€## ÂÐ@a~¨Ä’…‘!‹ÄG®±¾œÄeº‘óthpYbv@—Äüeq&þ"BäKŽÜûc>¿H²³Â&"+Ï¡¸7°]µ®ß„Iëx2µä ò_‚]é@ƒ PhO‹`GŒH0"1‰€©„"¼ð²T€=°à ðF( ¨D›èÑ#”Gæ}ÆDe1Qj,DîãD;žQ ŸìB¢ð`–%rD>ÜI kDï#RH»°&Êœ‡õñA¢Ó°Vf’æIƒºàÇl)׬DZØ b’8s¬;Ü¿,d¯£€IÂÀ ªè_èD–Fñ!œG2=zÄUçq0´CÏYÆÆÄ'ŇLAT53ÊÄ+pÿj4?j÷Àþÿ{…úšAh8~R¸“’P;Ãßá€É3'à·raÕøKý†ßË@š\xò,.85€<ô ™¾!€]œ áhu_“ DŒ±ctFÿ;¸Ä>ÖQ lB3][|Ä ›QI\?w×» ÃæÜP÷Öl=Ž›IçCÌNpñ«$<õðÚ÷§FVA’rÞ^[ù•Hèd‚hà;(»[:¹aK¸à&–‚ð§Mä*)M žµÂ¬p¬w¬+b• çªÂ½«ð°[T,Ré !šBË0³‚$- s N©ÂÖpµýD-¥ñ pþÂÞe¸l."e ‹ÑBãÂP¹$,Žÿ ( BË0³"A÷<• k'X;JÍö øá¸p;ÿ"Ox6óïÛXþƽÀ5$zÄ ºÝZ¿ÁEð[T¤í›­ ÁÄÃPvÁœÜÏ;B"‡sü"ªýÝ,BBJP’üŒ%Y¡ x½Âeö°›M$'Bß ë‰Â СšÄ(¸; CƒÂ•´ð¦ä)àY ˆ.B¦pªcŒ*Ìa ¹ˆB¯þ¬U\+/ Ñ"µ䰤k¼)=E VÓ—Pð¦Ld)±# sËžŽéÌD’t2¯~¯•ÉìüªK{·˜é¶<+/Y´[ä¬äûÅ{¿qÙOö̪s¾WÀ©@Ð6¦ÄOÁ¤ÇAJ¸ðYÛsbA­²oûÔ3‡þÁð6ðh £·W 9ðŠ‰œ#<çñŽÂD*ð’ëd%3 g“B`™}¬&¹‰ ÄêBs¤ƒ¤'‡‰ ë‰Â}LpŸÜt(q ñÂ…¡ðœ%w­ h¥Â]ap—òÜ&'¡ ”¢Âg’°š,&Æi »BBq:œ×úŸ¹Ê°Kì.¹Ù qS M*ÝÖò¹ŠlŽÇ¨ƒÅ>Dôïœ=öPð ŒýŽˆ?µúÿeä’1½E@s1ŸT¸.ÂÁ)vpQ#dÂɬÁ†ÍÐfSä§£êHAÉRu®ô>½£Áúh0&\ ì«_¥B 9ðŠt"ü‡Ý,B=ÿ°‘ ¼$v/ )XÂMI“þ %.· W{BXHЖ½Ü%Ö -Â%RŠ"œ"Àq¼üB2»°|ì#Žqð{Â?Pd$O žBJV*¦ÍÄ›*¹?š0˜ŸLÁ…ÃUXFÝ9þ.6S¸ô’ñÜ=1úsSäÂXúèx?ÙOÙ”+úÅ"ÿ¢®ÀcP¦  ½›À»ð8©ÄñWezA1ÇQà<¼ÍA€metkit-1.16.0/tests/regressions/METK-103/ok000066400000000000000000010773401513171467200202210ustar00rootroot00000000000000BUFRb€Ë 4Ë~hd!^ jL!ØbÀFV%R Õ.ÿÿdE¤F ÕÀÌF  €(!I·¾.@@ @@€€ €@€`ÀÀ À@À`À!Aa¡Á@!@A@a@@¡@Á@áD€!€A€a€€¡€Á€á!„a„À!ÀAÀaÀÀ¡ÀÁÀáÁÁ!ÁAÁaÄ!ÄAÄaÄ‚Bb‚¢Ââ"Bb‚¢Ââ"Bb‚@B@b@‚@¢@Â@âAA"ABAbA‚A¢AÂAâBCbC‚C¢CÂCâDD"DBDbD‚D¢€b€‚€¢€Â€â"Bb‚¢Ââ‚‚"‚B‚b‚‚‚¢‚‚⃃"ƒBƒbƒ‚ƒ¢ƒÂƒâ„„"„B„b„‚„¢ÀbÀ‚À¢ÀÂÀâÁÁ"ÁBÁbÁ‚Á¢ÁÂÁâÂÂ"ÂBÂb‚¢ÂÂÂâÃÃ"ÃBÃbÂâÃÂÃâÄÄ"ÄBÄbĂģcƒ£Ãã#Ccƒ£Ãã#Ccƒ£Ãã#Ccƒ£Ãã#Ccƒ£@c@ƒ@£@Ã@ãAA#ACAcAƒA£AÃAãBB#BCBcBƒB£BÃBãCC#CCCcCƒC£CÃCãDD#DCDcDƒD£DÀc€ƒ€£€Ã€ã#Ccƒ£Ãã‚‚#‚C‚c‚ƒ‚£‚Âッ#ƒCƒcƒƒƒ£ƒÃƒã„„#„C„c„ƒ„£„ÃÀcÀƒÀ£ÀÃÀãÁÁ#ÁCÁcÁƒÁ£ÁÃÁãÂÂ#ÂCÂcģÂÃÂãÃÃ#ÃCÃcÃãÃÃÃãÄÄ#ÄCÄcăģÄÄd„¤Ää$Dd„¤Ää$Dd„¤Ää$Dd„¤Ää$Dd„¤Ää@d@„@¤@Ä@äAA$ADAdA„A¤AÄAäBB$BDBdB„B¤BÄBäCC$CDCdC„C¤CÄCäDD$DDDdD„D¤DÄDä€d€„€¤€Ä€ä$Dd„¤Ää‚‚$‚D‚d‚„‚¤‚Ă䃃$ƒDƒdƒ„ƒ¤ƒÄƒä„„$„D„d„„„¤„Ä„ä…ÀDÀdÀ„À¤ÀÄÀäÁÁ$ÁDÁdÁ„Á¤ÁÄÁäÂÂ$ÂDÂd„¤ÂÄÂäÃÃ$ÃDÃdÄäÃÄÃäÄÄ$ÄDÄdĄĤÄÄÄäÅEe…¥Åå%Ee…¥Åå%Ee…¥Åå%Ee…¥Åå%Ee…¥Åå%@e@…@¥@Å@åAA%AEAeA…A¥AÅAåBB%BEBeB…B¥BÅBåCC%CECeC…C¥CÅCåDD%DEDeD…D¥DÅDåEE%EEeEeU€…€¥€Å€å%Ee…¥Åå‚‚%‚E‚e‚…‚¥‚ł僃%ƒEƒeƒ…ƒ¥ƒÅƒå„„%„E„e„…„¥„ń充%…E…U¥eÀ¥ÀÅÀåÁÁ%ÁEÁeÁ…Á¥ÁÅÁåÂÂ%ÂEÂeÂ…Â¥ÂÅÂåÃÃ%ÃEÃeÃ…Ã¥ÃÅÃåÄÄ%ÄEÄeÄ…Ä¥ÄÅÄåÅÅ%ÅEÅeÅuåuå†¦Ææ&Ff†¦Ææ&Ff†¦Ææ&Ff†¦Ææ&Ff†¦Ææ&Ff†–%–%¦@Æ@æAA&AFAfA†A¦AÆAæBB&BFBfB†B¦BÆBæCC&CFCfC†C¦CÆCæDD&DFDfD†D¦DÆDæEE&EFEfE†E¦e¶€æ&Ff†¦Ææ‚‚&‚F‚f‚†‚¦‚Ƃ惃&ƒFƒfƒ†ƒ¦ƒÆƒæ„„&„F„f„†„¦„Ƅ慅&…F…f…†…¦…Æ¥ÖÁÁ&ÁFÁfÁ†Á¦ÁÆÁæÂÂ&ÂFÂfÂ†Â¦ÂÆÂæÃÃ&ÃFÃfÃ†Ã¦ÃÆÃæÄÄ&ÄFÄfĆĦįĿÅÅ&ÅFÅfņŦůÅç'Gg‡§Çç'Gg‡§Çç'Gg‡§Çç'Gg‡§Çç'Gg‡§Çç%W%gA'AGAgA‡A§AÇAçBB'BGBgB‡B§BÇBçCC'CGCgC‡C§CÇCçDD'DGDgD‡D§DÇD×DçD÷EEE'E7EGEWEgEwE‡E—E§EÇEçE÷FFF'd—d§d·dÇd×dçd÷eee'e7eGeWegewe‡e—e§e·e×eçe÷fff'f7fGGg‡§Çç‚‚'‚G‚g‚‡‚§‚ǂ烃'ƒGƒgƒ‡ƒ§ƒÇƒç„„'„G„W„g„w„‡„—„§„·„DŽׄç„÷………'…7…G…W…g…w…‡…—…§…·…Ç…×…ç…÷†††'†7†G†W£ç£÷¤¤¤'¤7¤G¤W¤g¤w¤‡¤—¤§¤·¤Ç¤×¤ç¤÷¥¥¥'¥7¥G¥W¥g¥w¥‡¥—¥§¥·¥Ç¥×¥ç¥÷¦¦¦'¦7¦G¦W¦gÁgÁ‡Á§ÁÇÁçÂÂ'ÂGÂg‡§ÂÇÂçÃÃ'ÃGÃgÇçÃÇÃ×ÃçÃ÷ÄÄÄ'Ä7ÄGÄWÄgÄwćėħķÄÇÄ×ÄçÄ÷ÅÅÅ'Å7ÅGÅWÅgÅwŇŗŧŷÅÇÅ×ÅçÅ÷ÆÆÆ'Æ7ÆGÆWÆgÆwãÇã×ãçã÷äää'ä7äGäWägäwä‡ä—ä§ä·äÇä×äçä÷ååå'å7åGåWågåwå‡å—å§å·åÇå×åçå÷æææ'æ7æGæWægæwæˆhˆ¨Èè(Hhˆ¨Èè(Hhˆ¨¸ÈØèø(8HXhxˆ˜¨¸ÈØèø(8HXhxˆ˜¨¸ÈØèø(8HXhxˆ˜¨#˜#¨#¸#È#Ø#è#ø$$$($8$H$X$h$x$ˆ$˜$¨$¸$È$Ø$è$ø%%%(%8%H%X%h%x%ˆ%˜%¨%¸%È%Ø%è%ø&&&(&8&H&X&h&x&ˆ&˜&¨&¸AˆA¨AÈAèBB(BHBhBˆB¨BÈBèCC(CHChCxCˆC˜C¨C¸CÈCØCèCøDDD(D8DHDXDhDxDˆD˜D¨D¸DÈDØDèDøEEE(E8EHEXEhExEˆE˜E¨E¸EÈEØEèEøFFF(F8FHFXFhFxFˆF˜F¨F¸FÈchcxcˆc˜c¨c¸cÈcØcècøddd(d8dHdXdhdxdˆd˜d¨d¸dÈdØdèdøeee(e8eHeXehexeˆe˜e¨e¸eÈeØeèeøfff(f8fHfXfhfxfˆf˜f¨f¸fÈf؈¨Èè‚‚(‚H‚h‚ˆ‚¨‚Ȃ胃(ƒHƒXƒhƒxƒˆƒ˜ƒ¨ƒ¸ƒÈƒØƒèƒø„„„(„8„H„X„h„x„ˆ„˜„¨„¸„È„Ø„è„ø………(…8…H…X…h…x…ˆ…˜…¨…¸…È…Ø…è…ø†††(†8†H†X†h†x†ˆ†˜†¨†¸†È†Ø†è†ø£8£H£X£h£x£ˆ£˜£¨£¸£È£Ø£è£ø¤¤¤(¤8¤H¤X¤h¤x¤ˆ¤˜¤¨¤¸¤È¤Ø¤è¤ø¥¥¥(¥8¥H¥X¥h¥x¥ˆ¥˜¥¨¥¸¥È¥Ø¥è¥ø¦¦¦(¦8¦H¦X¦h¦x¦ˆ¦˜¦¨¦¸¦È¦Ø¦è¦ø§Á¨ÁÈÁèÂÂ(ÂHÂhˆ¨ÂÈÂèÃÃ(Ã8ÃHÃXÃhÃxÈØèøÃÈÃØÃèÃøÄÄÄ(Ä8ÄHÄXÄhÄxĈĘĨĸÄÈÄØÄèÄøÅÅÅ(Å8ÅHÅXÅhÅxňŘŨŸÅÈÅØÅèÅøÆÆÆ(Æ8ÆHÆXÆhÆxƈƘƨƸÆÈÆØÆèÆøÇÇÇ(âØâèâøããã(ã8ãHãXãhãxãˆã˜ã¨ã¸ãÈãØãèãøäää(ä8äHäXähäxäˆä˜ä¨ä¸äÈäØäèäøååå(å8åHåXåhåxåˆå˜å¨å¸åÈåØåèåøæææ(æ8æHæXæhæxæˆæ˜æ¨æ¸æÈæØæèæøççç(ç9©Éé )Ii‰©¹ÉÙéù )9IYiy‰™©¹ÉÙéù )9IYiy‰™©¹ÉÙéù )9IYiy‰™©¹ÉÙéù )9"™"©"¹"É"Ù"é"ù# ##)#9#I#Y#i#y#‰#™#©#¹#É#Ù#é#ù$ $$)$9$I$Y$i$y$‰$™$©$¹$É$Ù$é$ù% %%)%9%I%Y%i%y%‰%™%©AÉAéB B)BIBiByB‰B™B©B¹BÉBÙBéBùC CC)C9CICYCiCyC‰C™C©C¹CÉCÙCéCùD DD)D9DIDYDiDyD‰D™D©D¹DÉDÙDéDùE EE)E9EIEYEibibyb‰b™b©b¹bÉbÙbébùc cc)c9cIcYcicyc‰c™c©c¹cÉcÙcécùd dd)d9dIdYdidyd‰d™d©d¹dÉdÙdédùe ee)e9Éé‚ ‚)‚I‚i‚y‚‰‚™‚©‚¹‚ɂقé‚ùƒ ƒƒ)ƒ9ƒIƒYƒiƒyƒ‰ƒ™ƒ©ƒ¹ƒÉƒÙƒéƒù„ „„)„9„I„Y„i„y„‰„™„©„¹„Ʉلé„ù… …¢i¢y¢‰¢™¢©¢¹¢É¢Ù¢é¢ù£ ££)£9£I£Y£i£y£‰£™£©£¹£É£Ù£é£ù¤ ¤¤)¤9¤I¤Y¤i¤y¤‰¤™¤©¤¹¤É¤Ù¤é¤ùÂ)ÂIÂYÂiÂy‰™©¹ÂÉÂÙÂéÂùà ÃÃ)Ã9ÃIÃYÃiÃyÉÙéùÃÉÃÙÃéÃùÄ ÄÄ)Ä9ÄIÄYÄiÄyĉęĩĹÄÉÄÙÄéâYâiâyâ‰â™â©â¹âÉâÙâéâùã ãã)ã9ãIãYãiãyã‰ã™ã©ã¹ãÉãÙãéãùä ää)ä9äIäYäiäyä‰ä™ä©ä¹äÉäÚzŠšªºÊÚêú *:JZjzŠšªºÊÚêú *:JZjzŠšªºÊ"š"ª"º"Ê"Ú"ê"ú# ##*#:#J#Z#j#z#Š#š#ª#º#Ê#Ú#ê#ú$ $$*$:$J$Z$j$z$Š$š$ª$º$ÊBºBÊBÚBêBúC CC*C:CJCZCjCzCŠCšCªCºCÊCÚCêCúD DD*D:DJDZDjDzDŠDšDªDºbÚbêbúc cc*c:cJcZcjczcŠcšcªcºcÊcÚcêcúd dd*d:dJdZdjdzdŠdšdª‚ê‚úƒ ƒƒ*ƒ:ƒJƒZƒjƒzƒŠƒšƒªƒºƒÊƒÚƒêƒú„ „„*„:„J„Z„j„z„Š„š„ª£ ££*£:£J£Z£j£z£Š£š£ª£º£Ê£Ú£ê£ú¤ ¤¤*¤:¤J¤Z¤j¤z¤Š¤š¤ªÃÃ*Ã:ÃJÃZÃjÃzÊÚêúÃÊÃÚÃêÃúÄ ÄÄ*Ä:ÄJÄZÄjÄzĊĚĪã:ãJãZãjãzãŠãšãªãºãÊãÚãêãúä ää*ä:äJäZäjäzäŠä›K[k{‹›«»ËÛëû +;K[k{‹›#[#k#{#‹#›#«#»#Ë#Û#ë#û$ $$+$;$K$[$k${$‹$›CkC{C‹C›C«C»CËCÛCëCûD DD+D;DKD[DkD{D‹D›c{c‹c›c«c»cËcÛcëcûd dd+d;dKd[dkd{d‹d›ƒ›ƒ«ƒ»ƒËƒÛƒëƒû„ „„+„;„K„[„k„{„‹„›£«£»£Ë£Û£ë£û¤ ¤¤+¤;¤K¤[¤k¤{¤‹¤›Ã»ÃËÃÛÃëÃûÄ ÄÄ+Ä;ÄKÄ[ÄkÄ{ċěãËãÛãëãûä ää+ä;äKä[äkä{ä‹äœÜìü ,<L\l|Œœ¬#ì#ü$ $$,$<$L$\$l$|$Œ$œ$¬CüD DD,DmB* X°hXƒ¯À é"n`7‘óJ—ç…,8¨Ð](A²ÂDÓ¬+¤hé ¡ï>A‚(Xö°¥H…–Ü0¤@z"Ü8&gAiT u”œ$1¡<³ ¿\Æ|—Ñþ_h†\äMô7ð0‰ºÆˆ‰ä»¸)Be: ÈfçÃmŠ‘Ï"ŽääzˆÃïS Qq U€Â pZ/ƒ>RAê €O ‚®†&ÆÇ†¢Ô8~ßÒ…Y†~ä5§ñº­Aœuq£Æš ¨ÿ&È/PC(2&Ô‚š1ÀÜ´À`DÆB\~–P²E…ÿ(3^¶‰à{DÞ")Q݉c N}ÂQбQÅÀÚ/·¡‹7 Åìi”#g®çkÇqª=;÷^'Œ„ž?ýÄP,쬡P‚„„'tVÆ `cDƒP>4Pï5‡æDB–â/ÄWP™}Å:)Ä1[¨ IØ]³ƒèϰƳ 7MÑÇ莫xxÀƒáà)ĈdpªÀRõƒD†à÷]”àKp‚‘l=À¿†i6¬áÐ[\°Ch#Í¡, Ì4QÉ‚©@#0·ÜÅõ21[ñ˜f /Èlßãóèî ‡¦f>ârš‘– —Û™˜3–AÒÌHÀÙë`*Âáq= aˆiÕÃ…,Ø üXOXEß‚J (° 6’+fñhÊ‹²ˆ`ù"îïØÖ;Æè*8ò!ÕT| CûV ³á b@Ý®ŸÐR‘ƒˆqö®Ž K8B2п)†e€6ÁϬVq„B #¿‘+‰ÉQ­b¨xð·ªÅó¢1LQ—õ+àlÀ£+âˆíׇ¥>ׂBެ  |¹`,¡›T‹pî„| 'E!U6 ‚àbàƒMPÀîaßÑpÀ ¼L_‘£ ¼É>Æe4¦Íl¸m#v;päKÇ=„:ÃÁÜçˆzž£âˆ€Øÿkˆ‚ABLаˆ7äOR"çñ¤Hð¬H^’I¾ îøQ*"–Ë"ð¬oÅ~r,ÌÁm/‹Ÿd^§CÍ‚8Çv†VÚ3Žq£= Oll-ÃnèãØâ}G/:Q±ÙW y·cÛNExýA¢–³d‡M„H1"®!ÕÈáÔGébF’g¸ àsëvø*A‰ò þÐ}p„WT&!K½ 5ˆ`uÃ9–{ðéY‡¶œAb#ô–jDÎ'IÑA Š>¨S¡bª…ÀÀ±jŦJ.aw ‹îLa$ù!˜Ìe~N4Ê­ Ÿn«C‚Ôƒ8çrVè;Qã4Oì|.£ïäÙ‘È/´BYò™‰Ë\#M× ÞI("P ‰I¼Ký"m|×°¢Å+¢*6AX{ŠùÄYzBÙe6ø½†Ø0÷ñŽp ©Ìfý£E€˜˜Ø#FÜ@7¸ÄŠZ8t„#±´ú8ó0G´¨>~qú° 4‚3!^1bÈŽ/©‘„ Vüdg#0Ìò0ÒöF²t6kAº#Žhqí£œçSÐíöÇŠÜ=0ð=¸8t$ 4 ·É #dpCü²&¯kÄÄvI$©$b >6JÎ]9ˆmÐE â6šØ”c„½Þ&È!<þ üøƒL„5&"‚aÉ hJb^\@ž@… *)@ñP¸ »¨W¢Ê¼P¹:Åäü/ÿ†ÅŒle5ù˜ÔA†½26ÂÁ¼Ór“C¢}8ïN‡•š=„qòíÍ´€äz á1 nHn˜DMò)R@¼d{v$HI%³‰HôK Ò_Ð5” 'Àd2ù0&†j u{¨$Á;Ò ¶0\nƒ\z áK?Ü;±AêëÃð~&²"Á&ˆï€I("VÔ#8œxDþ„(ËÁM'ŠŸ$V¥B½¸·r…Öˆ/qƒ NÈd(£.¿âÒs®¾6L¹)ÿ4q¬šóCh퀆Â=Aï7°2„' ¥Ñ“H_ÀCÚR%œcŒÎät $y#ÞÉ9êJª\3Hšq„á8 nHnבzeñ؇Å?Ô¢ 8ÌȉËi$"'Ù‰tPMQÂx,ؤÅE@ì*ß]Á‹$XZÒãñ‹X¿¿†"1 ±“¶ ÓühO#P ìøÚÆFðô8`ÑÉÃŽ„huÒƒ¼'MÐõÓGÉŽ?%¡ÿö58ƒ\$(t!±Éó¢¾Eð²6héŒþÄ•¢%9,>‰}LÃ’lÿžD ¾pä^À)³ƒ€ Ë@{ÔJp%®áHk ø_”Ã2Žj€Ú‡p9ß¡ÜOˆ}á Ê!'숵°GY¢H`®˜ÕáÎ'æEá dðTÙâ´I P³É¹n.¤¡{â ”bW 2n(ÎÏÆ‘¤5c1±ÖÅoÚcŒfÏéÜÇi¨<&qçðuÐ}`ãø 0¡éÈBtBìÒ0(”Š÷ed#—¹ "‰žI¿²TÇÜ„˜œÄÒ’');tI÷,ê°®¦|.à„“  gáÃYЧ°ãîTôËb(l ÎYJhAÂ>É`œû…(*abL ~ø_P¦ƒ@Òã†Ì 8aÎÛèz=Ãí >±¿{|EŽB9Ó;0•1ÄÄ´&ýA>šŠ*¼SB¥¼šx°,œT-»Ñt›‹Ú``‚C¥ùÀË,†t&4zaª ŠÌnÃ}ÀZ˜æ-L\;<à;8{Œ#éô»q@H%(AÿP…@„_ˆ$¨a2Ö ¸Sr‚¶VˆÀ»†2"ažt _pn`CÄD0ðë¼Ü?™B +½ð‰GÄed$1&Ó lM"uûp¤B<Ò*¾1\» ÀZŠ"áäzð¿qȽ|4 ˆào;Qx)[8–>„̶';Á@› ;$Sˆb©¤¸ð±,E¤ˆ-ûáv‚!PbÀ°©ðP2ÚÁ±üeðyàL!Ö M@M¼‰@¯¢…³`/G!‡Ì ©hh£ƒ`BØ åq‡aØ<ºáójXƒ‘D7L"“‘M ´J1Â_dž…E)OQ5 ¿ôW®âÊØÂ*Umn D hÕƒ|0“àùç;ÐE6ÂDxüðž˜*D+e… —0`C´¶ÐÔZ†Ù 8u!Ñ<ôèzÿƒó" o! Bˆ‡˜Eèâ<ÚQØ•ó„Ê'*‘@Š6ØSf¨‘°X°çyî §ké•”XÁ'l@FÆÂPø]С¸CD+Éak¬ Éøa¨(@×z†ñX9=!×J%X|ƒÿ> Ó! IˆŸÐF°âCƒ—}DÖÞ'C% OtT*⮸…ˆ7„Öæ`ƒ3„O $(A.£ á°Re­ðH°¸öý41•ÁšA =mMC…,ÿpîÅ«H? ¢ÆšÈˆ.„\6#ºá$‡‰ZˆL€bq–ø€£E3Ö*vPr)Æhå¡ ŽÏxIà‚iÆ$@§Ò…tà-S!wú ,hdµC@ÐÜÝ®"ô:ÃÁ㱈œÄ !–qdÑlH7‚OOå€šŠ„ïH(PQI?ƒßh §aœ xKduâˆ@ªæ|.~! ] fECLì@àµ;,;‹Á鿹,Ä$Z!øáwˆêHübUvðœû–Þ€…½„c $ÊÁ3· ÀSªÂ¸–лg„28AŸ# e°nƒ"O ñ)‡¿˜?¨â ÚÁ؉gf^$ &ø‰nMÂv_GÀÂXÈœP£¬Rä,CAo” ç¨b¢/ÒT ÙU‡ø9³áÛD˜}}ª!1¯ G$‚F· À˜jÄÝæ{’ˆ„Ê,'ýMM ×ZBëD3PÈKwÜ5k¸ë1˜tñƒÂNè€þ ˆ%ðBÛ¢$pŽˆÙ™Š%¢a3Ü„¬à'!Eú œhX;‚Üž¼Ä•Zô4ƒÁ± ÷só¨sPúd¤AñBS(þв%.À˜£û)„!Y‚ 8¨]ƒ®ó€Îe†¨°6ñ¡Å “@wþÃÚ¸«Ñ(VÄDbB0¥ð0’ÙÂnÚLà©…-¤azk ?ðeWÃE€0ÞÚ,T;Áæ ›P€2ļ!ºaœˆÚhHa=b W¨V‚Ën1€ÀU†803m¡¨Î ³pêC¢xéÐõÿå|@ÞBS  ‹ÑÄyP7¨…y-x¡y? 5eCC(ïPÞ+&Ü:éAä«`á„Î!§¡íˆÔð*ßdY `_ÓC\ ðÓĆӨ8IaÏÞéøz¨ðf YA zˆXE½!] T]øC „*0ж\7_ÈY¯`xÓCáŽâĈc¨DÏ¡bû ‚à_{à‹Ó†Î08¡Î€ßzPƒíF Caˈ{à-$Avƒ  dQC=LÃÜÍì:Ž¡áÖy¸2„V!xÀ·ñà1;!—: &hl‹ƒÏí(‡Ÿ>¥‚¿‡`Béæ(`Çó†u 5U!¸#, t¹CÀŒÝý"lBÅÁzè CØewFz àÞÿ‡.H;Aæmžp€KÄ  ÐÇ8oD5&A¶“ taýÐÄüáˆ2‰¡­ y8o"“Òt òn‡Èø?óášA =m@Äúýàª€?b” l¸n¾²[ ñ¦‡ÂT?¾Á³Zhs“ƒ·^‘ûEÀ:‚!á¤x(s)C´ vpúdì=«å¾‚š…@è€*b/ ®€´xR€(<8À)À…Üqì D`WË­(Ó@¡¸@@8ï¾| ¨àk!FHœ@9»ðDÀ£`‚à —€ø œp€Öti¡ ÷à'/A5. ‡K ‚OÌ3`\i°›@§ø'g‚ãР´x‘È,Á\ ºàTЂˆ¡@¢ä`¼€èÐ!7óð K gÏ‚h3˜  Ðcóƒ s`Á\úx/Du¢ а[)‚ÐP=À—E¥Ø$˜Á²Ö€Eo!P¹@ƒYÁË’:0p׃~$¯€Û=ÊH5©ú +àh?ƒ9ȃ@ÉÛ=¨1WA†n ð_7ðX:à·§¨,šÁ_ ØUŒ¢œ࣬  '¸Á8ä ž€K»ƒõHkÀù8º =GæT°w{ƒ²àU`èl209AÃô ý@nʃlô"àÖØ£84ŠŸ  Õðew!ôÄ ÃÍ /´xô ¢ [ÌÕYà°§ D³‚!æìІl„*Ì!á™%(@ŸÂäã0~ƒèdø õ´›¨Ëñ¨µÐ¬´…^8*¶aS¦ ŽXSƽ`¤ý…¸(¿ACí ÈOôÂ{¾ºœÖÝ´&¯!3: ˆ K»‚Y^¨”„—È$va!tøàG=‚5<…ð‹„O„"4ArÍ ‡[¿‚Úx²ð´ªžH,°¡cª èWð‚»j¼¬ó_*¹S¦ Sã›0· ¤¦ü( BÚ ØO—xlà›Ï„ÖH&gA1 wpK%‚U„ Å!ˆ0Ô„¬ P`=‚þÔ½¦åÄ.ï¡u‰ p\hBߌ۵Ⅶà,øež PXZ¾îÓ€­•…d*ØÁT  “T‚œ*½`¤ä…Ä(©aC> øhkC?ráÎih3–¤ ¦HdÁÃ"&õÆ®†-¤11Á‡š -ø`ìƒ|ü ¾Òï$/4aw¯ ¬H\ØÂâ¬ó¶‘…«,-Áf˜ "ÈX“Àá­íg4*ôậ È mÊCjÎ;àØåÀ 5ÈÁ¬„ T€j3ƒMæQ€Ñž†…$3ðá“ Üøfq/n]ÀÉÛGl1ö¡Ú ] biÃW@Á§/àA|Ü Öx^*BíjG`¹AÁp:@Ð[tÈs5Ö*–ÀãÕ<8¡ÂK€o«ƒyد€Ü›Ýl6¬á³¥ ŒÀkõƒ[ĽPÔýŸ´4¿!£ì Àgôƒ;¼¹ðÌÕ†]°2¨Á“R ‰`cÎ$±àĈ†t<ó!æ "8x¡CÁ†ñ î¬nX;=¡Ø+±¸uC¥˜ €ç‹5P9lÉž>qsÇèpà†øÄ7aº0 Ám‹Ãh!P×÷†·ˆ5w©È =ØiqÃGB`ÏÐw5Ba©ê8~çƒóêƒ0ûEÓ„>gñ]|Ø{|ƒØ’¦àôV›¨<¡áãM Xwåûª¿ í`¬:ÆáÔ\’xtÃÅ å3!d8Ì¡Ä&p C|bÂ@Ý$†àð6ÏAµgØ„½D"Ê ûÁý1DAUÿ9è^ÄÖ "‘'ú0?œaûÊ0}çCë„<àùÀ`=Ç¡ì{Spz+Í>L@ñh‚¨;Ùáܩըv#íhJpér‡C`9ß¡Í"a@v#îø"¤ÁQˆœLD°b#ÚÀˆÄ=¾!Óa ºfÈCB`¤ð„·"f õË/´A?"3¨ DL °ÿk‡óð?aù¹}DÃæp ÷´¨=iáé[<yoƒÇ”0 ÷¨¸ôGÿB>jæÐŽÒ„sB#'ˆÒüFbÂ1m}X‹€„Xä"«wœ°D°b#Ú0ˆD<ö!Èq od Báâ4š„_„ ×ÑÑ&T@ô"{€}Ääþ3ê,@Â"UÁ¡ˆ”¨D¢"$ø&ø‰0¼ISâI;ø‘u„ˆ($&± mˆüdGªâ;•Ï`ŽÄlÐ#JarÄ$Eèâ-l[ÀŠm„O„"\á‡üD‚ᆘD1 !lA LœB/ÂÒ\@š~ÐÐ&o2°‰DLH"`˜÷x—^·ž%£ñ,>‰[PJ¨‚S›Ž”ÄœÜ$ÊÁ%h‰$h‰íO9Bx:µP@Dæâ'8(‰º M£kVMhšD̶&I‘1k‰…Kí‚]ªà–İ–%h‘*c‰KLJ""OiH’Ó„’‚${"÷‰´HMb@Ûù•+„§š)K°ŠWDRˆ"’ʉУꅘ(ËÁE– &pPþb†c&˜ ÐÅ4'ý?‰ò|O^ÂyM»x„è@'$Q8A‰»hM£k$KšÎÜ&ja2ɉ’ÈLz"b×è˜?À%ò/,‰uàK’âZîÊð–D¯j%mA+‰áLNë"v_¬¸'DçF'-±8ð‰ÃœNâo p›R„Ø &³Ñ5G ¦´M‚h3 ™dÄÉd&@11‘ ‰hL/"`±uÀ«PEW”*¥1Tn œÌT·‚¤,¨¨O…?\)ááN:Šk”S*¢—ű¨¥#%Æ)¡GÕ 7 Q„Š}F ¡ö…$(aB›Š¼Pn¢‚”` 4„ÿ°'ñ? ôpOŠ‚{AÓž_Äñ<'x±;U ׈N "t9šÀœªDã'q8 ½\MÕmÇhÀ› Å4)’1L! ]èRЕŸ§€¤ý…&\)$ÑH©ŠB,QõBްo@£;…(´QE%Š%DQ"‡4¨¡sE ¦(=‘A| \P#¢€nühŸ·„ûú'ÓQ>6‰î0O[¢yüÊhž!DïH,Ia‹ X ‚¾Õêð®ùÅtà+Œq[¨ ×V‰"²ÒŠ«ì…\*ÆUh ¥Tö¦¶/p©I…HŠ*7ÑQN †ìTb úP§šE:Þ)ÌMïŠk”SC¢™#Â¥Þ…-)XaJ_ OR\b’ˆ@¤ ÅŒ(äÁF© 2ŒQxB‹Q¢Z…v(}¡C•Š(P³b„Ó ÐÅg+-!XøŠÄ¤V ¯™uÀ«uÅZ*ÁQU¦ŠªU1b¨Ü?Ø©ÀELr*UR/ ŽXTS‚¡»˜§þE>0)åNžŠqpSr‚šͦ/Å/¼)rñK3ŠV|Rž”›¤ŸÅ# )HŠ>DQÖÛïÓÀ¶F…¯F-dQjg MÀZ?"ЂxX³e—Ö,§Adr ´X»¢Äf°°Q…€Ê+øA_jŠ÷ÐW¨¢¼dÜ®®Ås´+’±\% ݤVÔ"µ§¦ø­Åf:+&áXÆŠÂLUùb®Ño€«JX\*´ÑUBЦ,UB§É6x©{…J*A1Q² ŠpT7b¡% §åE=h)àQNžŠqÔSxšþÒx¦[…›ð,Ñqf4 .Y[É÷Ix²Å ,mqbî‹TXŒÂÃlè°wö,1_© ú(Wµ"¼¯à®Á…tJ+•Ñ\1ŠÞV×BµÀ¦ø­Åf:+%QX­ŠÁ„Uó"®Ño€«PEXò*¼¡UtŠ©LU.B¨ª@ ©ÌÅM*[ÁR†‹Ç ^Bïm¨»ÅÕÀ.–‘t‹šP\£¢ã¿@¸4E¾‚-Ü¡n‹mÈ[R"ÙûÈжů-l!k ‹TdZBÓ‰–д„…¢0-‘gÄ ;Y¿Íbx²Û…•,œQdr pXçbÆZ,±&‡n,.ñ`ú‹PX ‚¿RôP¯jEy^+¾q]vŠè”W.¸•¿ø­Ç…m+ZqZˆŠÑ$Vm²ÒP¬VÅa&.€±s® šP\¼¢å!à¸ãEÅX.ÑpŽ ´[ô¢ÞÄð¨·M¹ -¸±ma‹hP[#BØk¼PµªE«ô-Pj(‹MÀZNÂÑdžh³ûžH,â¡f½‹2hYtÊØO¸²?Ej,s±c ‹¬X™BÄ4˜°¯Eƒ¸,a`? þØWàâ¾?íH¯2xd0•ƒý p`§ÃàÀIÿZ/äñ~_‹í _=Bøs·à½[é¬/?Qy¯‹Ê\^6Âñø»äÝ^.àvœ ±\]uêÇPÀºMÅÑ.|so‹˜\\¦Â䇸¸±EÄ,.Áp6‹~0[ÕbÝãè·E¶²-§lØ cȹÐÅÌö.[1rŽ‹‘T\wââ÷¸fEÂ.±oÒ‹{t[ÈâÝð`Ç]†9\1Á¨ j c>C*ÃØÅìÆ.1cÁŠÓ Sb…ãN”øÄuÆ"1‡Ì ;¤aÁ YdˆÂø†40£‘„Å "¤`ÿC3PÁh† P0?‘Œ ¤`1§ÿÀ¿¿…üž/Öá~F‹ï_YbúÉØ¾Eï$/kzÛ‹Ó¼^~¢ó_•€¼zâ¤/¡wú ¼°]ÒÂíÎiÀ»×´.±!u> ¦Ð]#Ã6¨«ÍFe€3!˜ º˜e¬#,[hÊ©FSì2’á”L Ÿ@dçC&r.É>ÆHÊ29Ñ‘w ˆ˜d2 ÈÇÔF=1Ý¡Ž‰ qŒcpCìÐXÆW1(1|Á‹ŽŒXðb±£¬ŸèÄÍF$¨1Qˆb @Ta情mèÃ0Æ(0³1…) &ŒaCú8ÈÁŽ 0Hñ㌠˜`@£=Άo¨3pÁ›; Ö¸f£4PÐ̼†d¸3A˜ ÀØeðã.¿qHËXFYd2¾¡•Œ©Ìe;£(üC0ÉáFMz2bq’£ ’Àdyã# øÈjFA2¨ŒyÀc¸#àáˆÆÔ51‘Œ| a$bé㇮ÀÅ=Æ(^4Ë¡¥Ç )$icG¦2@ÑfFŠ4C±¡Ò thHãAHÐF3ì1ŸŒõ”g™ã<ۈΪFt&3“!œN ßPfçÃ6v­pÍ?Æhn3:™` Ȩf)#0š~ËÈÆ\¶2Ù1–r ° em£*ŒNèÊ?Pš2xQ“R —Ôd¢ƒ$e Ô€¢Ô5 !¨=tiØãMÿkHÓ(F˜H4µÁ¥c 'øi-H @PÑІ&4\±¢š´hzãCÐf‚4ŸÅŒû gƒ=LäèÎû†v3§qœË ãœgã7p´xÍ~Fj03E™ÐŒËfB#d*ðØnFÀ¶5ña®èt$kŽc[Ýب֦³ 5“¡¬9 _Ôjå£V—®xÕNF¨â5=±©‰Iôj6£Q‚¸ÓðFò4䡦Á 3°i„ƒKŽV0Ò†’Ð4ˆq£ø@hÏCE™(ц‡4*± ñ4h ƒ?½LHÚ6†Ðˆ6yQ³˜Ül·Cdò"àØåÆ.6$ñ°ÜƒÄl c_¬ø°×“†»p5Ï®- nHk_ƒZ4Ì(Ö/F°N5uñ«dW jªCTŠŸ ÔÄÆ¤ú5Á¨ƒ @øiîÃNÇoøÓTïd7haºø Õn•csü›0ܧ†äB7‘¸aÀ´mì£nèqÛb†Ù„6ÄQµ¾«œmCãi‰FÚ ÆÎø6na³ •¼l”ãdHجÆÃÖ6Q°Fkåã^gíÀ×<¸´5·‘­qhp1ãPßíþ<7æñ¾ìô¨o’ƒ{åÚxÞ¨ô7”!¼bßônìãvŸ±ÝV†éˆ7?Á¹³ ÊxnAqY†ÛþÆÞ˜6èA¶÷ ´˜m’kÈYÚš†Óv61´.ðlÜÃŒ\(ⵇ€8™ÄŠ!0pùã‡3ˆávÇ X8IaÁç àpQ#ó Xà+†ÿÌ7õ¿D ÷Èo¥C|­ß(ÞÓÆõ7Ÿ¼”âLnùcw² Ýo†éì7F¹¿ŽZœr¿•b¦`åG'9-É!FLr£N}ÀãÂGæ8ڱƗ1˜qz‹!TXâpÇZ8‰qÃçŽäpÎ#…Û)`áœ80aÁ8 p"C€Jý èLÇA9þáÏŸŽ{s¿C}å¨ç6à9­¡Í"fTsã˜P½Ð弇,ê9ZÑÊ‹ŽQ1ð=ø{íÞ¹ñà÷cG¹î=Äíål {PÃÙ×Êö*ǯø=vaë[X„z®Cí‘h ûמ>²õQ§Ð}.ãèá@ÈùçÍÚ>gòà”¬|ƒãÿ¸ø®‡Ãä>ÁüYàØ~ðã÷ ³ ýqGê?I‘úÍ´~^ò(XüEGàÌ>ý÷º}¾£í_ 9Ö¶@"Â×€cÿíùðÿ°Gü$?ÙQþsñ¤t#û$ÔpþwÇò’@é2 6D m ]ñÐH$@ŸÂ¦"ÜD‹ 8q—È Ä@Q¢ ódàƒ„% ½AĈ,ÆA^b ›Rè‚dŽ —Á’H#˜AB‘’”„~Ä#y!Q“HCI¥K4“óŸ4$õ¹'‚ TÞJ ²Zî; ˆ°)¶©Ú@p€;  ¤„È@Æ@d5 4lêw€Èf€5  p¼^À»€_€2ˆ Œ¶Ûô€Q@(èà Ü”€Ô€p 9а°Ø–ƒÏšQ@) à hÜ ¥€Øp€;`Ødƒ΀í`x< `÷ŠXÀ¯]À1pH H†Óí€|PaP28È E¶ƒk¾€ás :fLT,¢€R +ÀL þ@R¬€áp€:`Ô>NF4À¢€T`+À¨ ¸ ” Î h€5@X5ƒµ@}DÀ"hÀ ®¼jÀ»€d2à Hþ îA`ˆpGØ%€ˆ (F¼j€»€_ð0p| ~eEA° às Äõ&@–Q@*°ä ¸ ˜ÀÔ€n°:°@h˜~X8€¢€SØ+ ‚ iÜî~ Ä`e84€F&ÝÀq`>€ ˜0 `òŠ^³@]À1P Hÿ¶ô€‰€Gà%L„ 9¯Á^²ÀZ .  €x]AÁ@ë°à €@„Ô€ú‰€Hà%€P |xì|€Èj@8@° 4J‚=+Àœ0P)0 £xÔyÇpi(6°ZÇK¯_€28Ð&+ÀšQ@+À @RÂëà{ðAx"`ø ]Ó‚uE£ T`,$œ ¦ªzÍ`î À x¼Ê€p€=`˜0 0ÏŠ^º ^ð2LÖ‚Á€H¨%„ˆ ,‚¼y`Ê€j7èèØ£}K' à ð@ ÂõÀ}@DÀ%€\ (xîwÀÈj70Œç&€“àM(„f —?ƒLµ€ás ;t¸þ,–W€+À €è–Op( à pÜ ¥Õp€;`@L]R‚K:`©0[H0È´ HÖƒA΀ð  ð@Ìô,ŸW€,° (è–Q@(ðà ‚ç ©Ô€p€:È4°KylP ´^à1œx ¿~Ï€À @è@,¯W€2Jè&#€–Q@)8à ¬Ü ¥€Ô€p€9Hà·Ñ‚Ÿb€¹Ð`¨0¬ 詃|AÓ À hàèX.€¯Y@2HÐè&#@–Q@)èà °' Ÿ€Ô€p€:¸@ †'‚ºÁi »€]À/ÀÒ ä°‚‚0`î൰ ôÿ–P`+À €„Ý€ú‰€E°%€P (xÈg`5  F ‚‚AQ€¯Z -ܨ ·19Á° á`‹˜NXè€}K&È F.Âó}A0"hÀ š¼t@»€d5  ØvpE@¨ÀW€-P¨ Tâ ž Úp [ô̱K2`¸Ä°¥gÇ@d@<€¨ ÔL@,¢€W€.àl ж÷`–Nh(° ð…‚ÍqÀÁÀd(4,P± Uƒ¡Ãt@ð Ø@èôú”ÀM@+À ”¸€ú‰€I€%ÐP ðÜ ¶Àï }D8$0$ ÷£Á^¯Z / Z ¬‰hùA€ `L´ïÜ€}BÀ%€à øåÈì@}DÀ%hP Jxú§@èÀ}AÈ"”€ Ä–ÁQ€¯Z@.° |`ƒPÁ·á& ‹(ˆZ‰Ð€d>`@ð ,ò ¶€á|àA`$ P Dxî¤âyA "`ø WÌrAE¨ÀW˜.`² E<±à s  Ò,˜€d2   `¼ŽÈp€B°%€L `€î“Üàtp=H Hö¦~X8€¢ÐWh-P– @8©Ùàp€8@¶ ‹d:%€À `@$ô–W€2H ˜±`»€d5Àlç‚ ÁÀÀK2<Š uÁ¬ÀËp=ì+ø¯Ù„ˆA·Í€h`5ðà¿•ƒ¬B Á}p½HÉ85†ª”ìÂ"ÃAH‰ÈJ$à‘Œ Cl¡W€s`4ÌÔ…\v-€þ0„¼Ë•€K2   `x&Ë€ú@‰€K( à 8Ü ©Õp€;0lR+ úǪcöA‘à¸\]¨3¦ ÷™B“áX`‹¬Ä](¹\áÄp´èQà#d~Ô»ˆ¡E ¡D”$Œ¬‚èaA P·è€`_NA8jÈØew’)À¢(dŽ7è0VHå뀺øXH>~#]àMƒŠØ}„8fØ …Z‚æáz¼b<&NÁG2À `@ª[€Èq >€"`D `—^»€°P·b0D^)s¯ŽŽˆCäpÒ)!{È9PY“‡ÆsxÒ-À×ÀùþR<«•nÄx¡ÁQZ¡”|œi¶Kd™bÍÁe‘”¢€<ŒC 0†yÄ Õ°Ú°NÐ/0CY 0F˜ÑÂðø${>’!îUkâ®áñáý„·|)ÜCMÄûâ&Q‚WÃz¤_0àY!LM(¢µROíf¢:‚\Çûâlñ& „«ÛR ëÅFáŒËhTÒqæ(É€7¡1 šÈLŸ !.(‡„J¨1ÁÌ„˜Jsb°åHƒìy"yK‰Ìöã1ÒøSúö1§{©GÆ£Y2>iEDƒVA7Õ—‚Dã+¦Ï*§fóÛîËHˆ¶â÷¹ÀàRÝé}žJá¦RåçúûªÉÜ’óëuÕÁmŸ”¯FÌ”²"oCV›M=(Krd#Ûµæ4Ïd†£ÇÜê;Q-ú…<Ãè€í™|­LŠd=TI%;uõ,ŽM-!¬”×IØÁPqˆ6ú)—å@§à‹àg؈ ºr_õp×C­^/­Düó¾`=$&ŽfÃÁÝ¡ÎrL³Ä=ß6æ÷} ÅŽ£ÅåiÏŒEÚ œÕ¼3"£0‹ó:9/˜A? £Woé×#«¢)w2¦‡-TM§c†AhT‚?„8°O’¥sRK±°Ò0a¦2%€Àð  `þ¼^¨@Wà+à``ª¨@l2Ñ/xqÔqèò7‹¥¥ûAŸŠ¿Í5¦·r‚x©ÔV Æ*àLw9¸ œX/´È{’„)KÇ n»óŸOðH]ók5ÐZ÷ðz¨JÖ¥É·Ø ‰åÖßÀrÎ?k&.ßø LoÍêÒç\m$žÇ±†|Ø£òwý f\_.•—,ÇŸsyh Ô –›ÃÞIý$Ó'* - €Ö2HÖ¡pÓ ð–›´0)ïí˜ÇNŸ¢&P¯–[Ž)»œäçovº PÎèðìβ¸)ßn»FŸ¨ÍìÆë˹™ñ[1©ŸÞÁ5a2.ÀsKn…°(톉AÀ›0,h<+iÀPµ0-·ŽÖÖ-ìb4¦rrÌú’n½Nõ¨(e(ÀàØØ4úÀP@+À"x#xŠ Tœ»@rp[ûáÒ*Á£e¹6tZ‡ çvƒ’õA†2Þ¹~|C_¢4s˜ØÅ®ô5m¶ßÜ”ר!ü·¦HË2°­Ë¬œµ-«ço£¹Ý¨2àI}ÊÉ!g÷Pº×º‘9ÁÞ×7i=¹ßÄ/™¦b£8b aèDtª`«¸Z 9Ú]ñ~;¹Ã]Cn?7û¤Ñ°>ÏÆe©²iÛÏA(¶ô-¦5'ÿ†É<ò 1 Vö ¾rë+œJÎk&Bð·˜÷ëÇᨬåzp‰´íÛ¯,ˆ€Ü¸Ò" ê³dK€2@  `Æ ‰ê…&!±ˆ´¸sÌZŽCû1mÞ}ŽP·ŒëqËžãÜxÄ:ÙZÊÍ)&ñCëÒ*7R‚þGàßûÇJãÇ•¹Êâ@ªAr¦hq„8+Ëë–ôç¥h‚75Úº­¿‹´°T Z ŽxGvâèa;(œ8r¾ü)›ˆAK¤°wçÛÛ½A÷Tøe^˜­;¦3ƒÕ ó’„À¿Û¹ .~åÖ~WZ;«'[@ïV6u*1¾²1™%•1Gz$Å!1CñaÚâ1l"²½Ùö Q4"ûlæ’j 3DgTtPÊfõ„.ËKS¥<Éb Ñ9¸ŒØF@m‰<ÀDÝïΡKý¼ë#|>^{ Ÿ^5Φ]Y0®åSëèw“8ûÔIþ 8åžÇÅÓàÞÈRÓíä–ØÀd(¶/›@måg€›˜A¡'g‡ªTR<éÄ“WÜì¥2dþH„´@Ÿkï3§Ì\Ú"­„ó.†W ¦cI”}BNžƒÕ§VÑ ØGóá¥å\ðþtù8Ù]ŠnŠ˜ ¼Èü¸ÌèS¨ª;–WË ™w|½ÂwÿFuœíDoŸ;oG=cƒQ´ŒÔËqЏš¯ï&ÆXj³@"¥QÛÌ‚gs‘tu* Ù xâº6[j DæX[v!`Ë=j$-ŒUkéå”Ã<ú^ƒù>ê ÖHøáïǽãÁÍ ØncP±4–Õ ¦…„Z¥å@š&«”Õ¤k²²Êi0<[ž7—tø¶ú˜V o†R²½HÚ ´S-V&²i(îÔQ:hý§qæµBÙ ô%Ñ’åY8©Ò]P•ãÉ­çõ£ÒMÖ¦á0jb1ãÔ*ε§âÕáf̸–®ÄàO>'hû¥e¨¾¸~Tc)=’‘jZ…pZßžo##ƒÒAÌ]2ì*%~‚„y!¾ŠÑAL#s“þKîúÃÌ¡ú#÷¶^©ÒI¦4@r-€÷H•)`@Odæ%1Ç×ËFéj*†2Fþ¡KŽ®çÔõ¦Äê*;+–x÷®‘M&dCIÌ„ÎäŸÕ‡¹º$X䊙½ÙµÔÆŒacA©<£]Ums4M©”ÔHaì?䙡Vª DbÕ©¼Hôúk„-{¢É IÅjb½yPd–øV "Œçˆ…±Ø˜öÀ“¬Bé/$ … 8 <(µC‘òO`zC–,ßf÷4É ¶e+œ¹%¹-±p‹¶Vb ”¬¤e()ÑVw¤Ob’¤“D™%1/‰ÈQLfé‘V!‰*A²‘8D°'0, v eÀxéàçP<1ôhŠäœ'\"a$é¾RÞÀ×cÀÙF†2Ñ“ ¸hCcpñH ER”¬ÌEi3„“I"ot¼°UÛF".qe ðW‚Ë(ÃF~7±à<ŒäÇ)hÌ:j˜ NZ£²ÃЏàP ‰’§L{‹$RÂsà•„º'1J‹ _C;(õÈfIbྦ|8qêšÄÚ©éiL%hk€–É^r4Û`”ÄL ü‡èA"&x …~0Q¨Žœ€äl&áU ¨fyžAêM:›Ö†Â&†8 á0‰Üš§R%± ‡œ8!ª jC€Q 0Q¢×8àÄDÂ_à·¦J7àPXŽЩµhl%h«„3ªJ&y‚4pm`ªH,aƒ pxÄ@&AXŒl#Å!‰)ÊHZ³›Tï('FúhÔâ´¶4•Ä3‚l]e^!€æ4+1 B © 7ý ¥Ô4‘Ø|’Å- ŒÍ wt£•5j~Zãšxä'©AÆ4 ¨\nrƒ0 ÙøKÄàðˆ°O¢×ÀèH$HÒˆtƆÓ;ò ‘à›µI-ÍŒM\s+ß!AAœ+¡`1JàH‚Ô Pbš!¡7 $e£™ i"Ê Z›pñHBH2uZ¹FC6Ò/¬†¸€CF0ˆƒh ‹@ô fü'!yƒÄÊ,!”Ž\ÄŽ(ÁjÌŽnÃΡe$ òV‚î™dÛWc¿š"ƒ`j¦°h€``@Ü 0_ƒÌ%Áp È‚DÂ,!•p‚Ę))n̶pCÜ!Ý(JWÒúYÆÞ×À¤T# °V ÐLÄ €BðÀÊ \°%!k ¸‚DÈ,q™˜„dª)ÁtLêr#í¢u-ªEYcÚ@âç¥AÐHAÎ XF¤  60à.À`Z¨%m ÐƒÄØ-! ܆äÀ*‘{Í,tt£%3ª|[;ÚÈçwÌC" Põ€aT ðP¼ @1@Tð/ í `]†!±= ŒjcÎ"‰7Jæa3_ÍhþN¢®RÊfØ;!ýЇ…¸jŒ0Wà À/à@0`|º MBþŠ4_#mQ Y£´ôÈiIÒ…Uø¿y8ä0M‡L "<`µ„D ˆÀ 6àL @#„à¡<¦ò$ èGžà-€ÐÀ0 œÀÎpUƒN !2 š Q8D¸'JJÇYúîØpËÆ¡7-Ë~…œT£í)餚,܇A<úPʌ즑BŠˆWêÝ×èÇF}6Án›~!óÙ!K®s4L 8=^€&°à P€H2L! ˆhƒö%Ñd èvä=&aEÊÊ[S™tÖ§;qóPb‰t¥­; JUòÍ×dÃY´á¸MvëÜ  X¢G¢Qó=Ÿm(F<5¡Ìdƒd`%A<Š|XÂïÈÑ&â9ñçOú†$d¤Í3êT¾Vä¾ö7³Å¯Nt“Èßs(yFNGáœ}iò€t‚¤ M€@(@€Ð `}x:Â^À舸R¢Êφö;¡ýüÄÎ(ÉYËn`£/šÜân>j Q,ôµ'aI ¾Y¢ëØ\Êöš6ñÉ.Ø{l!?èñJ*fÓå¤ÅTú+!u kãñHÌJÂ{ ²Eã1¹£MÌtР ÈÍIªh”"¨E}-Ñ~ pg›^\é'‘¾Þ Pe½8ªSֵአ€9R€)€àà ÀÀMH"a[ h„l&N HacFðˆDrF“X¤%n-é„LÌkãŒÔúÈ7DâARàå'+ g ´a›-pÛ÷%»uíð… OãÃ(¹šÏ–“5P°u³ÃQ PQ½ Ë†Ô:ô¬Ž¸( SK8^ã š\ÞK=RÐÞdŸ¦µCjŒX ßðdž}6ÁN—yCï «ÊHâ\3¢=ëaf뙆&éx @¼@¸@B"|°¡œ1á¹(„Ć'QT‹|cRxóÈ EBMŒ¥Å|.a‡Läl£’žü(BE:Døž¥-«9h«Àaã/š„ܧ*»‘îð…LQãÓ)ŸO²”W°¥µ¯6`®5Ö Œ„È)af g£zÀþtGòc”D«…«/á” Np­å(~G"S“r¢•M¬EqLd#AÛágR<ÙùPb‡ôgä‡.ÉÌÑ. 5»³ÍÏ0€ÄØ`¼€€¬`  ~€:‚Ш…à4ʰ‰¨(a]‹ÈeCeøˆFFbV“Ô¨Ž.ñŒ mÛPþhUEÊH“Ÿµ6+jëÐbs3Z¢Ý—2»Ññ…ÌU£ñ)é¤Oî•õc±¸ïS‡,¡ƒ (RÜP߇¨BâFÀ«Â1‘© @Y  ýØNºðÒ‡0> hžÅX-ñ‰,pƒ¾ÙÈøLƒ•@³eè1Á¢¾ssÈŸµ ˆ®H LÂ:{ƒ `Ð80x  _àì0HB€Á†œ9¡õø’„ð*qm 4hc{¨üˆ^GY“à§å‰.©‰ ìlƒàúc¨ŒÃÀ°°… &ap@æpƒlÚ;ú0–$,ሠXtî!ñ% ÜT¢×Hφê:Ñô˜ŒÄ§'YLŠô\C ŒÖ§ ˜^À ›„œ#A(?ô~„"a% àUBäÙX?‚#hžL-Q„ ìn#¨ˆºIâp”­¥¸0!”„´ °ó‡ 5a ÈX¤ ›¬$aàGBFàž<,Á èoC¾ 1 HO‚¨¸ÁÆt6ñÓxƒDW$±6 :V2Õ—ØDbqCX0À¼,!T XQ‚¢,+g àdÃ\°ö8FBZ«…¶0¡ž ¼tÃÝ ¹É$M"Š•h´BèxC φ80!v pZB΀¶…Ü0• PpƒºÁüL‚Œ°¸† 4¹Žœ{Ä"‰#ÉœQªh@è˜pb@͆P2 ˜fCH â‡h>bp“Ää)‘`‹°cGÈêÇÂA‚)’<™¥ *ˆˆ„`ò‡\9A ànÃväPì@yÃÔðüˆBÂ*–Äò)‘]‹€a2èãz?‘p’¤Ò¸‘j"ˆdBÂЈDX#¡%‰€O“ˆ´Eê1±¡¸sCÊÙ ÈÊIÒk‰¼L"Vh’Œ$&‰TL"p¦b,ÁuŒ4f#Wë²@’À•àè£Å 'á= äO‚‚`¦EP+Ái °a#(PÛÇ,<öh‰„%¡;€+qY ¸Uâ³б¦.1| 2” ÄgÃN݇:Áå°‚8##IvNÁ±xkC[øÙ†à7ÑÇŽˆw#ÓÈbEr?¤šÅøæ‡09‘ÏŽ˜vCÀùÇüA’‘\D &I= D=‘ìl|#걈0BÒ"‘„¡&); *T lƒä%!H˜F;@•„Ì'qDŠtVB0„Œ¤m#¹!‰,J²apŸE)éX‹JrT’¸–äÃ&‰9 ðQ••$­eŽ-©¨E¤”Ú£UŠÕ`bŒ´”RÂ_Lé½;¨¤Ôò«²7ùbDZQêFIÉY/¦t䟔Z›™óö•Õ»o/rAHM"TZQòGJ)y6'Õ © ¼A²fcÏjMU¬=¹½‡€õCúrCÈ#ôœ˜S²ŒTËo¯öBÑ[Sw/ŠÈË$æñ¤UNÂÛƒlpYÖ< øcü‚¢"Fi.'U «VjïbLÝ®¸W\ö`,2‹ò:_NúAT¬)Œ2æˆ×›£ˆrΑØ<¤û d0‹’*`Oªq^®ÊÚ›|tÏIÿÂØ¹#%äí¤L±–ÒòaÌ© 5&¼Ù›“‚sÙì@]¤ÔØ£zÓ_L…¥7WBó_Ü*‹R.^NêEUIÙD)åt¶—ÓcŒ‰•3fØœ¨zG©u@*E”¼XÓDnu忨U¤d¾ž4”Š‘²JLÊ!V,åÀ¹2ì_LA—5&øëŸ$‹ÒŠuSk u±V‚ÛœãÊP®.Èù…=‡ˆõ¤ Œ²‚TÊ©S*e`°–âþe YÆLÊA]®v*Ñ£¤zÐ"ÆùI6Eš¢PK ÁL,Æ Öc˜töBˆá2)eœÃc’{¢=LÊE_.¶4Ò[Ó«{ÐF"Ç™^#Ä }!à=%Å(²ceaÊ=Èi&(%|À#Ž{Pª>M*Ua¯BÔ\µ}r(HYvÃHb áx0†pÞ„0‘‚˜Y ¨:ˆ'el¿#|ÊCMêqe/¦TÖÜkÀ~¦/I9•-¦ˆZ !(#„p’¸a aØA‰@,Æ@á„dœ•²þiNaõCé);ªeªÁY³gsO:CxÛ(åôÇ€ìƒ d AÐB aX1%Hƒ茓²¼a YÓ?¨¡*¨%b¸X“CnÎ¥îÁ(‘¥¤Ð—ÓdƒPÁ!`¤ƒ°ŽC(x˜` ÑøGJe1†Ðî „h˜”‚À^ …©¸gtûá$Z’"qÍ)Ú €H p: A€> Á€;ÑN1$Å(¸s€z²CN*h0fÙœËÍ€Pâ7JY¹9Àà $ ,81‘&+†`ì!ÄÄ«—ãLsÏÒ'JŠ Y.6(ћ˭|P^&ÈIw<çð@0   Á)†¡'EÐÙDp –smÏ GI¡K¬uðÊZãxæFY74èX€€ÀxàÜ%ðî$E`ÊD,—•BôhŽa÷DIA?*ÕºÃÚ ttïrÄxû-ge$}   €À`ƒ@ŒÈŠƒoòBQ Q‘7'#¤Î¥–2öaì¡ µ¦æã];Á{oÖB¸dÄÏt‘ÓõF®Öšë`lqš´æÎà\Ó´yϦÁès#|¦˜3v|ÑZcSkP€$°"Á86 p9‘B/À÷"ä䮘#Rtâ'GÉQ5¨%2¬Bà_ E•46¸Ý\{¨xOqûÁYã}“2ÒhNºHê\¯&ŒÛœ³À}JF©-0§…©•òÖ]̳v ÚœvïAõÀX?¢¬p‘’žaÍùõE©•O­v 0"ÀÈ!Àô'† ð#…(½Љ"¨^ Yž6'ìžÔ†jCK)ÁC©åj³"übŒµ£5öòäcÅ{ïæ Âè“#ü›–ÓJvКKPªõz²ÅÐÙ“XoΙç?ˆE#Ĥšú•U‹m¯&ÈÙãUmÎл·¨û D#‡±b9ÈéU1§ ý£4Ö¨ÖÛi( À|‚ÀnÂÈn‚dWŒQº=ˆ‘0*„¹3,j ÙϨa¼QrPK©­áÇ©T‹zJÍ(Ê–mL`¦ÜÊ e&r¡W°é»vp»ýž_o^—Æsî}è‹$F)#vúÉ#4¦Â_E6žpQ)rU5*ÙeŒkpq¿@ãs1:kœ.ÿç˜{Ø)ñØûÇBd¡q刑dZú8M"”[Kñ&èSñ*8e=¯9_ú´7\1/$ØlMFFÃ3A¡lÔ‡l"¶û›ïî/§3#¦áÙàðy™½ß$Ç哸Šu:„`C¢†­©„§’d:b¡uRê*ÕÓë0µ»"îé€Ä;d0³Ú EVÁ;ou¿ãs=:v¤O›kÙØïªxX<®Á¤§ýÊúŽI¥§a ù…"£IZè² [H®ÅïL<Ö@s0é –ÔCl¶ûÛòÎ2Ç5c¨MÚºð•yÜXN0'%¡×ð’{a?i ¬Ú(²ô}âQÍ2^žQm©íÕ˯ÂêU~8Ã’cô³ š E–ÂpY¿žãnszº˜]¶oW Ù«èÕZk"6*‰Ng:#¹AìPþ¸ƒåDT#b’R)z傇Mœ«ÎX[­dWIkï6멘nÐojB6‹ÎCaÕŽî x²*Ì}¦?C&1™°Ñrk¹7œÑNôgÅä ŠÕPþK&&ê b•Z’Áj¸º0_x0ãLÇF…«Se±¼ÜÅpE¹œùN´7uzxºŠ\Ö.œ—¤ÌÆ838q¬ˆßdtŠ<ÞÆP’h¢¤~Ua5È fRá*Ä«U•ÒŠü…‡ªÈdff4GZ©m•Fê+„EÉŠè^uì;ÍË¥mò®)VÜ­(Xt-˜§ÌX¦v³d Ç€îþ}?A‹¢?ÑÚ©JäÓz€mKT«X0-dWRë÷Ö!ã#iš¬Ñ«jï6|Û¼N‡+;£ýÙSž(o“ÀIÊê€ùJŒ¬Z /v 9&úã­Ñïe ˆ9G'%“IÊõ.R­Yaz¶]‹0Ø™ì—vo»IQ­Ú¡oM8›\ÄN›·iÁN<øKY$T‘ňÛ$|¢Oq4”¢¦V'-Ϙ]Œóæà£9ë­Ô‡ÒG¥“NjÅ1š¯Ebž¶œ]â°/˜±Œ£–uëL}®²Ûro²8ÎÜÞ¨’„Á,ÄBÜ .ʇîd’! Üš\RÏ,q—ØŒÁ¦ÌãIé­r‡ÑG-¥-Ó^ Õ6²²Qd&·l^M°gØÎì²}{P°„ÜYp'9 œû.¶òB‘ €{°:9ÿ Ö £¯á÷y¼“¦P9+x€ ¢æÄc›qéÕàˆ=Gu¥Yvª•>Z¶f ¸m^Ò0ª˜ðL¦…³TQ²œÝbpª¹HŽÆGY³œÚ9ò„ _ô"ûØÖu"@–#“™Š¹…ÔC&±Pçf{A¢EÑúéfôæJ‹áQ⮵Z .hWÚ¬=†Eƒ5Y£ªÖ2m6·Ÿ\M.cWNó®¡Øh7l‹Âv¡D€¯œaæ7;‘o‰°…Wêy”¼Ùìtˆ=ÿ ÏQI‰ô½òxHªªHX-h—_ì&)s'íJÓk¸6ç›ôî9G:ëíÙ†ë‘v«ŸÝ¢ƒÑ@0?("?–‹m£ãÑÂ*6x«Ì^"3‹¼‡×4&/U%n™VOâ)}}kE¹zò-ƒ`Æ e³´-ŒVç{ƒ½É èŽv;{™.èu@š>x³ “†"CªBAÑ`€ÑèzfEê'L•Ë ô¦}óÞèþš†«Fߥ&gŠå> ¶Áfθê_°ÓYìÏ–ŒcWÑ´jÞOq$9ˆ:®Ö—pp<Äb4ÅBi᪑ذØj°>Œ#Ñ ‹(cQ ȸô–Dr£ÿÒÙiÖ‚§-_dµX]e°X¡ìŸuL®üÛ·oä8íœï޲wu»½|A@öÆ(¡Ð×H’\Z7¬ „’’ i¥Àƒ$©³péâ|³B¢ßÒO‰“Ôý—ñX ±Í[²/2˜>ìo6]ÓAi©¦Ù"n¥¸S¦ndsÀ0J–Y°Ñ € øxDOÒ1 Ÿ' ¸…k2û©Ÿ à6x?Ý¡ÌQÊÉSôÞê‰1Pò®dZ®gWÜŒ?æG[6™¤hÖ›mj7»\îk—Sc¸âìÛ´ná„Ã`ö B #Ð!½¢‹9ÆÌÃüBG±H µ c]5Öîrh1ÄSE¡0pž·RªÅVkhEßk™ŒRÈ’e{³S™óÍ6 ëY5°àÚ‹nK·©ÜÎ)×$[¡U×òí¾w¾¼LÞ\KÒuþ A‰šÇBdÕ³™ËÍ ¦—CTq®~Ù`m¼7`[ñîwÓ•ÒBêóv^;¡ž7Õ B2Û (ãBHÁ!§XeÎ<"‡“ƒJÙÅõã=©¿Hï`^C]£vR—ɵu*ŸÁ[¬°¼YÊ-–×#+»õòóɆøÅõd3²²™¤,ööcO™¬*Ø ¢)R™ªUf áõ‡ÚÎñlð¹?]÷¯ŸX!,9¦0“!Í• Í)g¸´kZzm`Ái¸²Þ_p+¸’\†Îb?Ó§5×2í]w¼6Q/CG®»Ýµòú–AU!9HÓt…2Oé. š‰Nà(6Ô}ªp%Oš³±_”²“Z«.×WëÕõÿS ±‰ÒÇWdÛ3™Ì ¶–ÛSÙ®:ÙIm®7Z›íÇk”ÅÎèâuZ;]Èÿ‡ƒÍqêö¢|¾r_kÿa[¢ÜPt*çŒÈÇ1Ä "A!?Œ¯p_Ž3¨›¾ŽÑ£CïÕ ˆƒEþ#ØRX©aÊêr?X¢ÃRä*/uÊé‹*нmâ¹’^¯²˜)Ì<Ö2"m•ìÍMgÌ´wmbæÂƒi™¸ÒÞpp6¸—œ‰b·@ §a×Bíbw¼6QÏCG®Ãݵòú•~^%GÌdò}ÀŠÍG$gÉ‚”ÚÊyõC&¤”SȪ ­Kå˜×pÚ»^×0ØVlRæ<{'ŘΔhg4Áš¦­u–Ë›n»ßp¼8ØÜ©®r÷Gó«ÙîLx¼mÞl¯P·µSàùóžûY~rŽhF ‚XÂÐeî6Ôö}‰äúb·ÉyœË´mC8w&Og½sû2 y °‰ÃF™$ Òz©qTÒ*ui@Ú£{S<*X‰ ñÕJÒ™nº¹ý^M¯Ê˜4ÌBv4ƒ#¹–~Í“gê4ƒšˆ-f–ÃûjI¹2Þ“pF8Ÿ\Žd·A;§Ù×€í{w™¼9žR/Dw¯KÝéòúž~¿jäæãeAÀôçÀwo=¡AÈW$Fò0Õ ’ÙK&MSŠ)ö…z•P¨«:W ,8skdÕÇÂîq|NÀ a1c˜þ,¤¦dã;m¢0ÓKj»5ä[4­»Fí»~±ÃDãr·¹Ò$.¯7e›¹©à2ñÎyº½JžØO…wÏí©ùàþvö›Ç]Œ!ÁXäÐw„?¢"GJEs"ðÑ” ÑPl?7áœÒÙǤÃîBÝ P‡ÿE¯#§’= QTÂm‘<è¡oR3©×UGŠÐÕ~ÊÊyj²¸]M¯K—õL"†$Ë ’¦Ë£fø4 šMMI&µ›cµ¢ÜÓoh¸1ÜVŽIç3³¡5Ô<ëâvÓ»×Þ!O+¢ËØ1ï8ù*}Y¿_·ï󸔔¨ÜW¢-u—Œ4æPãDi¯ØÞìrâ;+pÏ¥( r"ÙH…¥ÒìI§tìJ‚5G¦qT¦«ÕÞ ¥¢úÜ1sX¼E_`0Ou,a&Cs+ šÏNhÂ4ëÚ¹­~–ÏÃoù»úßípð¸ò´Îw§J{¬eÙ¸î™x&¼|žsoTw·+áÑôûŒ~‡¿£ pÈ9 ‡îA`  ˆ5$FbAñ3èŸTRi*­Ëneêc)”ÜÑ(kð7¤ªÎÀç•£å¢E®†¨Dò#IÒ i8´ÚfÍ9pŸ´QR)dU ´upbÃ)g ¶-\b.Õ»ì¦K¹ÉÞf3œZM-Ö§³\5²@Û'n•7ÈÜ"î/ç'šÙÑL'`”H wåfâʉpྀb[2Äš3 €æôs”©×Tò<|h?Ó »Äh•Ôdj>é%ª•ïL{¦ÿÞ*µ&RžTâ­AWþ,ª–« Ô"ô)~üÁïb,±®™!ŒµÆl»?E¤Ô+k"“;ÉCD…"=!8”$K\&y“¬Ê.bª)_,´è]90 ˜Ã ¦’ãba½ØåBuÊ<„ íÈ)d.b#¹.2I %US ©µtò*„±H¦èTØ« æËe¤zÜ™sb¼;_Z0Jqì^†Aó*)™ M!'á %.B§I\²¾[Ë/AKŒ~¦mcN1³ߘrÖ:úžB…çô„2B‹¯Ge¤rÒ› |äÖRv¹A0£tS*ByJè%‰ZÏ9lʸõ]¾¯|X ,,¦)IW¥‚P™'¶ÕÊ ¥â’yN̪~W,|–Æ‹«åþC!”$ÏjjŒ6°NgçcÃÊñþš‚XB´"Qo甋zQÁ.¼šLNš([ªZµC‚¬‘[²°†Y“-l— ¬uêþ¼§:TM* ™Šúå•RØñt¾@aS1èæ¶ÓqyÃØçªv«<É!ï&ô+*!YªŽ@Hœ¥RáÉžtæZ~aDÂ¥"Sôª¦U¨ªþµ”JÔyoFº+Ÿ•ª ×oÒ¼1a²–Z{-ò—X ã¦Ñ•”ÏJj6FÉŽ9§H3¹éèXùÀ»AQ¡`Ñ (´ÄqzD='à–ÈLЧÓçjµ&ÑT:¬ÅW·,€V‘‹p²Ò)iе”[`.R Ïeýã YŒ„Ê$g4šßÍ»gÓ–AÕLðz©>· Ð_h\Dr-™t‘Iî%§Ó. Âä÷†ÁHÀ§TÜ«UÞkõ ixܽF_B0˜KÌN¦=+aœTÑâjø6‡›ÓŽ1ç>ã²Ñã|öä~@[ ÛÐèt\²9m">“âKK¦VÉì ª}M|©]Uý«¤V"†'SáÊ.fN3ÜPM^ÆÌÓv Ã(åúu5;ÁžwÏŒGí¤ ‚ @‰EEõ£§Ò(É@µ:eM8ž¡P¨(úÑj‘å]j¸Ýazfì3ç: Cæ¸ãh¡»$árz:=¥ÏG±3ë1ÿ-x„¸C¡¢rQŒèïDŒŠP½-ž™fN§§”(J<Õ3£­VÞ­ò5Ç›*M½&ôó†ùÉðè¢v<žŠŠÇèäÒ ‘ *‡úE7£=‘í餤\I32œ)O\(QTyÊd•F:­4ÞŽpb8ÔœÁŽ’gc¿©ç÷h}¸?ê €P†Èh„FŠ,Ù,I:%;’ìéžtâò{‘B¸£ÙS(ª2Ufg@³ª¡ÚØðdyÖ=ÃWç(tB¥"‰ÉF #–Ò‰0ô«ª_I4Žœ±O¨bÔ€*fEF¢¬Äïfxï=(žñϬ‡ñ4Ò Õ L†¨D\¢·‘ ¨ó¤‹òO,˜iM]§DÓîj!šMQÜ«I>?ŸvOꨄz HˆDÿ#ÂID’ÚRI-†™M¨'fü*"¥#Ú›9RB€@­ ´ÐŠˆ`=¢%áªBGž$OkIV„¼Êg 7ðž2P1(§œ rJò Ñ ¢†3Cã"VQ`èÌttÚAé$Ì”dK2&ÓRIËör„F8¥VSÀªlÚHƒL¢,iTŽPH¤st©X”»²eµ6è{OÄ(i”wJ]µ@¨d‹€Fu£—Qþ d™ÂSñ-‚˜œM<§ÓÌ*õò‘­M¨‹UO#±’iD™*S,¼˜Lê&çÓ®éõU ŒÕJ^§&T•*Ì@©5„¦zY/°™{M§6Òj¥Ú}L§éTîªô’¥)gô¿"e}5Àœ|O 'ñÔ0ª4e(’›…QŒª¡VC&“3 ¯$ã2w¡>ê¡QV©TÂj}%M2­ÅZ’›VNM'ì õÒ¡K§)Tpª£•ŠêáÅyY?6 íQ)(ïT§ªkõBª§ÍW4­HW|,0(j(Õ¢”ÕM4¨TÈ*ÄÕ•êäµRÆqHL¥iSYª•,ꬥbZ·E^¦°ëYD* •/*¬Åa¶-]â°sXü,ßÕ` Ã…l:»Y``±œY†-$VÂ*îÕbÅáeª´7ZѭÖ1K,õ ŠÕ©mz¸#Z®­¨ýË”E¿ä‘tÖ»³]Î/8—Á  ­2šRB –‰\y(”E;¼¬}.BÈR§Ê©Á_¡-6%ĨÀÍ>\; ×1@á)’e_ô±•–á"ñ*`¬PÐi;&(ðENt¯µ­òì`-ÌWÉ”ÇCR(sàšâfVÊ‹;s"/Î&%\É×™ØãMþ†!ÐÙ*Cÿäï¤h"ÆÎ[ûËß¡‡t2NÆs¤Ód3q²„ÂP°‚ûCvˆy5b¢2i˜PÌŠ‰Ù^ë-‰åäd­S8i M‚¡¹¥8J)Üé ´v„ÇвŠcCˆh{ÝÈ"@ÔLÒŠ)IâÑKD+<Šغë.s¾fÇ 2!°¬7MGPæ?ã¶ìx—ÏFÉîç>Çç4ÿa 6¤j‚ïP|R/BÓ(g-f!û$D؉A;â)ÍE$ÒT¢FCbÇ\ŠÌÉŒ3D¦—°Ø|›³³‰°suޱÝâ<¡®¼øöŸ{ƒú,€ˆ6š :Aé¨L‘ e!£”:̈Ñj&Eˆ¬©"øÒW´O>Jna^+-¿…ôˆÅ¹JælPMáÁÆS9öga¨ð8~#ÝŒ}JÏØâ @¶*u!1D-ø†§ð!3D‡èœeä"Ĥ]nŒ@Ñ™A!Ú&ƒ¥h¬‘"òâb7Ì»¥63Æô¤ãô“µÎxÒÏXyò*?§û53 ™„â„»¸º CÕHˆ ˜"„$V‹mQê2™Fš¨ÛéhRT$OfJ†Ácr.¦æ<ÊÜšFcÀo–MaÔ0;·‡š ÷9Ÿ^ù€±PDZ ÒBV(\á ±!ôôEȉ’Kª,qEæÈÇ}(£j$q¤Ž»Qç1 Š#ÎÄÍà¤?•Íàn`¥LžY£¦6G¦þDåàm3Á²z}Ï’ùÞ@ˆƒ¡$ä.††ñPÿ¢#ÜDî(«=ø£$g,IJ:âG èü z§ò!ÂIêÉó¡TÛ-JútÈ©š,£e@p=Žo¹Ù¾<·ûJŸåD ò‚ûÐŽª3C„H‚éo"‹´X”‹æ•R5…Ghêí‰#ôÔ‚ÐÕ’)ÒFö+D„ŒÖ“(b–\XÁKÌaŽx44FÌ$áT£ºPz’ûH@jˆ*i›!qÔ9*ˆ]0 *E½ˆÅÅT£zôtòCQüRAËH~©½#é$š–˜5pÇt‰ö$†ÄþH­!—7óòhM›1Ä‹:t'ƒüöqt¤J‚;‚RöC‰™"¼_”Œá‘·ª:G¡¨þÁ!$ITt’3ÒU’LIÆé?e(¬Š‰&6C§1‚&;еãgÓ= lù6a×&<±‡È8þ‚ jtN…­ê‚#]E¨¶Qò#^Ôs6ÑÿB±H¨©Å$ñ$¿›Ô“SJ’)WØH,Šg1€p7>G执(…‡XÀS™ÅShüraNÛÙêã?H…Å¡cd;ˆ‰ Sj/£Fˆâ?#ÿÔ†`‘‚’EòK&I®)=í(·¥4$©è•¤ÀZY{KYIp8E–Š<¡Ä8ŽÈ9ñ.;*…ã Ìº›S“™¦x/O‹yÿlAièVE"]X쌌Qºê;ÙHiÑ#u¤Ÿ„™L“ÊR‹RSJ¯ ],s¥§Ô·æ—T’ô²_ÕL©ˆ-2>¦O±à(† é."¦% €·!™TkètM:AùTAQý`"xt]òVQ×Â?âH„)ù%±$çô¢p”îÒ°bXK?énñ.±¥í4Àz˜aÓ2céL É˜ 3‚¦w4ÔÒêDÙHÂÀa¤£è¯j˜õCn8uºO~jeBXH}UÓ£!´r¬ÞR%²I,I¦©B¥)ã%i´²–ÔÒêj_0LI‰u1ì&Qt̪™ÚDi}MOI­U6&ÏtÚ¨›ûSÐT¡ ð‚NXb1rŒ¾axÍÆqß2?dè@¹ ¢Ë„m$§’*‚JÙIò)Ní+’%£º—ÕÓ âcjL¤Išá4¦–ÔÕ@šëSeÒmœMÏ©½98' D㜎S–js%N· ×¼ ¶…ÞaB1µà¡t¸7hǬÁ­"4bH;12MEJb)_=-ô%õtÄB™.“7ªhÍMT °™6½¦ë”ߢœ9Ž‚rœNm‰Ðq:f'U´ì ¦S¸Âw¡OIâ5=´f…xÌa¹P8§þ¼£‘ôŽê”bÒÆâ^†Ldišù4×&ÂÄܸœ“Žs%N‹ÉÕ­;4'tDïüž/ÓÊÂyçONÉë¥=±'¼øFŸ"ÓçB}FO³ ÷•?¨pl‚0¨Û 9ªè¤¡%F%®É<šÎ“}ZsN²IÞY<¦§ªÔ÷jŸ-Óìj~BOÚéý?ô¨ÅT D” ¢›P; %A (&Å0 ¯”RƒPi ¥AǨ;ºuQ·ª/íBW›êA‘Fó¨Ë•2¢äZÊ‹QbJ+Eh(©å¢ŸTRêŠê…¡Pwªµ?ð§â”øŠž¤SÈ*waN½©Ñå9€§ಛ¾SmŠl©Mq)ªe4Ȧ‰ÔÏŠ™¯S/ªeLŠ©å1N¦Õ”ò±{V мýW*ÔµX´ªÜÕU©ÌU!Š¡YSÎ*oÅL°©lÕ(ò¤ŠT~ÊáQw*'Cø¨a‚ ­TªIOº)ðe=^§”Tïú·S­JtNp©ÉE8°§ÞÊ›Skjl©MvÉAXÕÑ &_£²›o'M1õ•1 õþf¼(W'RÛªZ€+6Éd%,;Õ€¯•Ôú¹V÷êÙ‘Z˜«?…ež¬p•…ª¯ÎUÛŠ·ÙVªÄEWª³•Pr©iUê USÀ*nL¤©rU)Ò¤¼TˆjQ¦*-åDʨ ¢¡,T*‚P)ýÕ? §ÏT÷Zž©SÌJxiNï)ÙÅ:¾§G–*ÃDX/Šþé_«ÉåvZ®tÕÃú·VVà ÓýYþ«.µd¬D•Z¯[UЊ·V‚*ÃåW2ªº•Qú©«U Ê¡ÉSôªu¥M ©–.¢¥`T ‘½R*9åFv¨·•2¢.T:*†%P˜ª õA:¨ÕJŸÁSïñ°Þ!*A·Èê›× U§glƒy‡4¯ûuçZºp× *ÚaZ‡«Figƒ¬Ìµ• ²!–4Ä´X`K-_è+äõyö®ëÒº¹4WjÛåZø«Nõgú¬ÄU‘R±ZVj¿ W~ªä5[0«8ÕaÊ«ŸU_J©™Tî*”…Qˆª=ê§DTت™aRúªXJR©0U#z¤ Tw*‰Q…*,%Dਈղܨ[:ë\!j7­uŸ*³]–ZÚÉ}XóK¹b&,+e‚Œ¯öÕôн7W€Šë™\Þ«‹eo\­«®Z´ÓV€j̵Y(«ea–¬U{2®°UÂêµÉVfªÃåWTªÅ•T’ªU/ê¤ETL*ƒOz©×Õ7Ц”TÆ*—QR¾*QåI¤©!lmv‰jPŽÁü¼¹·BâßšâCBeÌjí†0•뎻A—J*åŽ\JË|¥n-—õ­Îµ"–‘¢ÐY«0qe,¬‰uޱZ–Ò•X& ÿ­_S«ØExήÐÕÒ:¹:W jÝ…[=+Yõiœ¬ÿU™ê²}V8êÄIX.ªûå^2«ž•o*­KU—ª°ÍUÚª³ÅU†ª”Nâ©zU!Š¢yT#*}…O©ÈÕ6‚¦nTÄ+í-{\¯'Eݺµ—;:ä$\&kyMmÒ­“%­¢µ(“ÚЇYÒk3EeŒ¬—%ä±›(bçXLk©_ø«í5{`¯*ÝbºªW8jãE[ú«qõlˆ­bU¦³ýVjjÊaXô+•a>¬U{Š®×UË*·)V«*Í…Xʪû[«UTJ¨ýT誗ER"ª.UBäQu†0™òÿ¼W9:ß1[ ;I³fºŒ” ‹f°¬F ¬ÀÞz÷^o‹¿v .…Ë̸¾×:Ý©[g‹cÁke­Ke¥d´7ÖxbÍeYwË(Ídd,u5‹ü±+ÖÚÂBX"‹_w«ÞÕyÔ®üÕØ’º&W*ªáý[×+nålF­Z¥ò´VkÊÊåY«µa̬•~ʯPUÚê¹eVòªÖÅZ«$UaB«ºUkª«ÕUKª£FsbÌVKC"Hcp U‡É0£V jÀ$—âjø/^ËÃavÍ.¥ÕÎä¹'WÊß|[¤ k©l]-kµ©Ž´¾V‰âÏ…Y½Ë1ey¬˜5h±¹V,²ÄmXh‹É`,Å~*¯„Õé’¼FWlŠêQ\Ü+%pd­Ûµâ¶ VªJÒÍZ«7Eeʬ”UŽj±DVªÁWç*õ]Ä«šUp ­U¥J²õV/Å`ØsÁº_ÏûØ‘vúNd¹¾Ö6RV´0ÓôZ1£=Wf§lµñ“A1ýf3|Äþv ¶`£ì~`¯åꆼxušë¬]ë˜qÅ.彤·+Ô’Ø“ZÖ«S]i•­•ŸÐ³˜–g:ËYE #¥cÒ¬gÅŠ¨± ÖòÂX!+u_•«äEzƯ"ÝâºæWD å\P+nvßt›ûfÆk‡ I‘¤š´ VqŠÌOYSS#Ùc½ `á‰u°ßfÔÁ?˜ªý _/ ×ùyk®ûUÙʺ„;ºå\Tkåo$-Ä•´–¶VµRÔøZk‹Gh"¬ì¥šì³–VbÉ“Y õc ,Puˆ °¿V4A„Ç&!ö<å§c<èÿœ¶ Š4oÆ­Ë™´+µâÆ©¸ÒøÚ;;ìf˜ì·¥“Õ²æ8JźX# Wa ìµ€Ž/×óâ½®Wð¼]¼ë­=t]®eõÈ&¸zVþ¢ÝÏ[~KhQl1-j¥ª2´ßVjИYæk7¥fM,¶e”ZïÝx[¢1r·î'…¿A7=†ÓBØZ¸3N‚hÓŒûùœ³ÖVTÉSØþ+šb¸ D†q°‹ö ÄÀM×îBúu^ëËÑ¡xÌ.î•Ø¸º{×<šån\g«„åo¥-×%·4¶|Ö ֪Z¥KN¥i"Dj¨^WwßÛ£àÎxÈnäÝÖh:§)¦âcÛö{t®mZ­‡¬‹5 †’2Ðs™×S4‹eÊ좵‘—±âö2”Å3˜ƒs `aLu€±¯âõò½ü—©Bòi]ü+µMuƒ®‹µÍB¹ Wšà¥[Ù‹tim®­œwž¢ð®]´ËªÁsãîP Ĺ·ñêÆÛ[;Zéj_ .¢63ÜVnàÌ]_&wd/¬rŒ1>†žÂü˜B‹Ò`1Kù]}°¯ˆë°¼ÊW…ºîE]ë§esÜ®[UÇ‚¸{ @Ãïô|u/^9åÍ»úwhBê6Gq%ýa» ¶ÒfÉX×,Z§cMÇhÙ­a3Dæ]€Êe$sìckì\•‰ˆ°ô¶( Ø&kµ_Õ+ï|…/fçȼ]×yŠìë][k£õt½õ7§8ò Ýè±àtè.ráÉY¸Vÿ>Ý®qóeðkÈí[§å´‘–…ŠÏ0Ù¸C1•e,ý‘s±ç4ŽÅŒØ“;Áai¬å‚k°eýì¿ Ìöõ^’‹ÈÉwþ=²÷ 8ñNÝÓ+¯çt¸.o1É8FÿäÝÓxûgEk÷­b¨Ý4´¦ŠÏÍY̳4>eå ©}’Ù2Æ:ZÆOØ«sÓaÊl,Yƒï0MvØ¿Ì×ãúùü^ïï39á6;ƒW\(é\ÖÓ‘›qÎM»ð6ÿ¶Ð®ØGÑËS’i¨mÙ ¸3¿vm˜Ìm™hC(d„Ì€ ޱ…–)fÄOØo³ É`ù ]/ö¥ùÎïö±3¬stch=È‹¸‰×´Þ …ÛiulOn¹ªª4ñ¶’ŠÐâÙò9f†l¾•2köElDzXØkrbÌC†Ò0©&zÁ:¡c«tBdÍÈe8‰'.Þ>Œ‹jwlwMtM«uµ6–RÑgÚK;^fÐŒÇõ–À²”ÆJrÈ\˜í[&bÕŒMéˆ&°ÔÇeêc]C˜ƒr î" Àd7–fä¤ÚßÛ&“^ƒk-JA¦~4y–„äÏc™ÅÓ4Ceû ®ý“ݲ>F@\Ç/ØÊS b]n¡ Ð9§ @âSyõn_±™²õµü†³¶Õ Úu›IfhŽ,ýñu3fædRËÙPÃ&KdT¬|…á1‰NVç̺ÛÈq޽/7;vÚVÙ¿[ [Kj³A}¥”´cöƒÏ:YÄ4Tf ±M”I2OvCljòÓ–ÜqòÎ!…À¾·¬¶è¬Û„›?£bk­\¨ê´Í¶øÐÕöÃ:fÊlÉ•—<2­&NZçkܲóTq ޽½œ·OÝÆÚ; ]ÃkÍMm§64š†Š8Ð*™ã[8]f‹,Âa–v¹ÏW+ìãÆC àou­Õå·Î¶ž†È|×¼ZÎ+TÑiý-)£d4'&|†ÎŽ™²k2—sŒV Çn8‡PÞý°kpMmX•°µ¯–¬@Ô[Zf«HdhƒíEž3ƒg7¢åHuÛˆqpJñq»Q7†×Ù’ k\2jìKI§"´Ÿ¦‹€Ðl™îƒ”ØqÓî!ÅÁB·ÌVîLÜk[bÛg:lDuA¬VµAŸjÒÜ;CIr‘n9¹ÄF¸,úPÝç›’;m m­Œ­¯6µfªÊÔCÚg‹HÇr‰.9¡ÄF¸/6úêÞ[—3mÛmÍu¯Ã5°F­<Ô—šr+“÷qÈN"uÁ•7ÝvñÜàt[i¼l¡-‚ ®µ|§Däôqcˆ¾pl-øe¼7@–ތڣ[/ƒak¤c½ªk99§,â/œk~wo/Òu·õ6µ†ÍŒØœZñcZrm8-Äg8n$ÅÂD·ÿÖ÷"ÝÈ—[n¼q*NíÀ·¾–ï<ÜÛÜ'“€—oˆ-àIÂŒ8 †ùRÞ"Ü«|üp,@:ù­_;+æ-|š¯ õón¾W×ÈJú;_¾‘×Ïzù—_'ëã|G¯ƒuï¾½á×¹zö×^ÑkØÍzó¯Xõꂽ:W¤êôO^€kÎÕy´¯1µåž¼ ×’ ñó^6+Žx–¯µáR¼€ ü+_zkíí}‘¯¬µô澆×Îùk_"kâí|1¯€µïf½Ö׸ö·^ËëØMzݯV5ê*½2W£Šô#^zëÎ%yž¯/µå^¼˜WúñÓ^2+Å=x†¯ µáWã ü _v+íe}{¯©õô޾{×̺ù?_ëâ=|¯}õï½Î×·ö‹^Ç«×zǯTéê½'W¢zô^v«Í¥y¯,õå¼Wúñ±^-ëĵxu¯ •àÌWáªûÝ_p«ìµ}j¯§ÕôJ¾sW˪ù_ká½| ¯{õîνÃ×µºöi^ÂkÖíz¶¯Ré’½סzóá^r«Íy}¯*õ伇׎šñ‘^)ëÄ5xe¯•àŽ¼WÚüa_+îÅ}¬¯°õR¾”WÏÊù¡_)kãÍ|M¯„5ïÖ½ä×¹Úöã^Ò«Øõzó¯Y•ꂽ=W¥:ôO^€kÎÕy´¯1µå¶¼£W’ ñÿ^6+Žx–¯µáR¼ׂ:ð;_ˆ+ï¥}ȯ³•õª¾ŸWÑ*ùÍ_.«ä}|c¯†õð.½ï×»:÷^Ø+Ù¥{¯\UêÚ½HW¦šô{^…ëÏ…yʯ4uåö¼«×“jò^;«ÆEx§¯Õá–¼"W‚:ð%^kÀm~6¯ÁU÷z¾ÙWØjúµ_K«è|Ö¯•Uñæ¾)WÂj÷õ^ó«Ý{v¯iUì’½|W­*õM^ŸëÒz-¯@Õ炼Ü×™:òÛ^Q«É-xÿ¯Õâö¼KW‡Zð©^ ëÀÅx¯µßò¿WßJû‘_g+ë…}D¯£ó²¾`WÉJøÑ_+à…{ä¯wî2½³W³ªö^º+Õåz•¯M5é½WŸjóŸ^jkÌy\¯&ÕäV¼wWŒÚñY^!«Ã-xD¯à¼WàúûÇ_mëì]}_¯¥Õô ¾kWʪøý_«á5{ú¯yÕ¾Wµ öI^¿«Ö•z«¯Oõéf½W jóÁ^nkÌyr¯)•ä–¼‚Wêñ{^'+ÃÝxZ¯5àb»û×*ûó_skí }u¯©5ôv¾x×ÌZù5_«â|¯}Uîú½ÉW¶jö^Å+×EzÁ¯Rµé¾½$W¡Êóí^sëÍMyƒ¯,Uä×Jñ›^++Ä]xj¯ 5ࢼ×~Êü+_xëí½}‹¯«õôξƒ×ͺù__!+âÅ|,¯€ïR½ÔW¸ö«^Êk×õzׯUuê½/W£*ô^ykÍýy˜¯.UåF¼•×JñÇ^0«Äåx{¯ Uàæ¼ WÊï¹^%«Ä5}ÿ¯ºuöž¾½×Ôúú;_¼ßךšó1^`ëË•y\¯)•äבZò ^=+Çxͯµâ²¼NWˆºð÷^«ÂÕxI¯5ࢼ W€zïù]û+¾åwË®øÞ»Ï×Þêû…_e«ëU}>¯¢Uóš¾]WÈúøÇ_ ëà]{߯vu׳Jö^¸«Öez¶¯TêB½=W¦Jô§^kÑ=z¯@5ç¼íWœªói^hëÌmy}¯,õå^¼£W“ òA^CëÇÍxé¯ã"¼[׊zñ-^!«Ã­xe¯ •á¼ׂ:ð%^«¿•wç®úÕß»Ú×zªï5]ãë×õzí¯Zõë½Uשºõ ^›ëÒõzH¯FU芽WŸjóË^sëÍýy©¯3æ"¼¹W–*ò™^NëÉ]y¯ •ãÒ¼q×:ñ…^++Äåx‹¯u᪼-W„šðs^ +Àíx ®ÿ•ß²»îW}ï]ì+½-w”®ð•÷b¾ÖWØ ú©_J+çå|Я”µñæ¾&×Â÷ë^òkÝ{v¯iUìÒ½W°êõñ^¸«Öez¶¯TÕêB½=W¦šô§^kÑmz¯@Õç¼íWœªói^hëÌy}¯-µå^¼£W“jòA^CëÇýxî¯ã"¼[׊zñ-^!«Ã­xe¯ •á¼ׂ:ð%^뿽wç®úÕß»Ý×zªï?]ãë»õ{U¯gõì¾½Œ×°:õÛ^µëÖ=z±¯Suê½:W¥êô‘^Ž+Ñz¯?uç–¼ê×›úó]^f+ÌEyx¯,UåF¼ ×’ºò5^B«ÇÍxã¯uã ¼YWŠñ#^ +Ã…x_¯ õàú¼WÚð]ÿ+¿•wá®ú5ß»Ú×zZï)]âk»Í}ô¯¹ör¾¸WÓêú%_9«åÕ|¯Œuðò¾W¾J÷q^ã+Ûµ{`¯jìê½’W°êõñ^¸«Ö•z¼¯TÕêB½?צšô§^ëÑmz¯@Õç¼ðWœªós^hëÌyƒ¯-µår¼£W“jòK^EkÇýxî¯Õã6¼^׊Êñ-^!«Ã­xe¯ •á¼ׂŠð1^뿽wç®û•ß.»Ý×{ ï?]ãë¼%ws®íî¶½Ë׸öã^ÖëÚ-{/¯c5ì½y×­Úõ^¬kÕzНN•é’½'W£ŠôO^„kÏÝyë¯:µç¼×W™êó^^+Ë=yQ¯(5ä¼Wªñó^:kÆÅx¯U↼H׈ ðá^ëÂ}x>¯Õàv¼ W€*ïå]øk¾µwÆ®öµÞ–»ÍWxšîý]Û«»}Þ¯¶Uö¾­WÒêú_5«åU|~¯ŠUðš½ýW¼ê÷q^è«Ü•{|¯lÕíB½W²Jö^¿«×EzÒ¯W•ꮽJ×§úôß^–kÒz2¯C•è2¼ûWž óŸ^nkÍMy˜¯0uåʼ®W”Êòw^IkÈ­y¯•ãz¼f׋ÚñY^'+Ä]x{¯ Uáj¼$׃šðQ^+À=wü®ý•ßr»å×| ïa]çë¼¥w„®ï5Ý¢»®×tÚø_ kàÝ|¯}õïf½ä×»:÷;^áëÛ{[¯hµì¾½W°šõç^·kÖez¶¯Tê*½=W¦Jô^kÑ=z¯@5ç¼íWœJói^g«Ìmy}¯,õå^¼£W“ òA^CëÇýxé¯ã"¼[׊zñ-^!«Ã­xe¯ •á¼ׂ:ð%^«¿•wç®úÕß»Ý×zªï5]ãë»õws®ìuÝb»£×ßJû‘_g+ë…}D¯£ó²¾`WÉJøý_+â•|<¯…•ðZ¾W¾ª÷©^ï«ÝE{’¯o•íš½¨W³úöS^Å+×õzè¯Zõë½UשZõ ^›ëÒõzH¯FU芽WŸºóË^sëÍýy®¯3æ"¼¹W–*ò£^NëÉ]y¯ •ãÒ¼q×:ñ…^,«Å x‹¯u᪼-W„úð}_-kå-|¯5ñ޾&×ÃzøC_ëß­{߯y5îνÎ׸zöã^Ø+ÚU{4¯cÕì&½|W®*õ™^­«Õ5z¯OU馽)×£Úô[^…ëÐ5yð¯;Uç*¼Üך:ó'^_kËmy\¯(ÕäÚ¼’×úñÿ^;«Æõ}㯶õö.¾¯×Ó:ú_óˆ\«À ˜è&—3€ªŒE«âêþȱmš*ø‰ùÿâ\øè6”!å{ˆÄåó)þL #‚j„€”uØÊ'ž0â ajb±Ì£¢&‹O‰’B&0(Õð§<š!µ¼./. ‚£ê ¡¼¸&½¼ G]‚9*CB‘ÀÅÐ.Ð àb›ÞÀmÌ%Í»Zb X{Õ&ú†Ýžèaœl6¢@Ãïx.´8 #¹‚¨5`¢h`&Îè FJ‚7Ž@‡¸H x´3Œ×ó˜«>(B tlâ8X…IþB£‡VYá¸ôˆgŒÐYtº]!Y" QR<-„†ûÚ€@Â2S‰¡b Üz@4Zv o?ôb³èÀ*Д 3fn ”BX#ZØo·…@{Óq 1×Î ¸–bÀp¥”&žŸ‰U"ˆ@~f,ù†ê†ÁžwèaüÁÂVÚ¡A1ÐK…^Æ„0@üÝ€;²(AVÊN@/í€ \–‚²!à£ó8&õ† C‚3ˆ@†-pï`›HÏ|cmÑèÎr@0n>‹UX‚¥©žL$Ò[”vÿn wZ¿xÍ‚µ ZWU„òÁ(¸(Ež¾YQƒØ@ç¾06•< àøƒ `€·Ý+|> K‚pk “ì€#äR¿ùÝ`xƒæÇíG•#ZNȺÖ.Ôg æÖ¢ˆ[`–p<"ᜈ—Áߨàoe@Û±úeðØS]Îp ‰îáÆ`?•Êè?ƒ—ÒI1t ¤x‚½ª€¥là'’ ;-æ@„ ;"c~¿íàj&!ô‘Žé C~·ÈÐÏZ0Š#‹@±BšSè™ßþ#ƒˆ0®Á㼈o¥ž;…÷„¡aȈRzgmÅ!2˜=›d_ýƒ\sàÉ]è/0¬ ™0 œp˜$Ð6©¦‚ ~€{.0¦ÙÝ`a³ Üq­ ?#¨(pÙÿ2~ §õ"®ûЂ$3‘ˆMaáç}Ðoá´²ìé’!\ÁP{¨˜b„Nc`ÿiÐ;X È·6]€¿¤Ð,¾ tØ‚r ’¦X"]¦(ä#€q¹È° G.y§ÀX¶ÐÞöçFqº#×÷èäŠ~4Èø c‚Æ•¢4ä$ÿjˆl:aë? p ž“ÏجAV•ÐN£–!)¤@õ°¸8Çn #}ƒ ·à´ê@*à È‚GÀ‡üð»ài gªØ9D«œSL OSˆŽºU\^¤Wé§”<6ÜÔ£+¢ð¸¯Ö)Þ‰x·‚#ù°{ÑFY&p‰SâÖG]#àÿ¿¨:£Ê w-ï ¶Ü*Bö Ää‚CÀ†-p:¹­° cØ`<dÍAT J¡èY¾ï@À7ti&Ÿ¸Dâýõ#©ÈÕbò09¬ Ù(ÂnŠp‹l²5ÆýÖ‘íØZpÔc”>Á ž<Õú ܃*¹W8*i– ¾t‚<¦àƒÔ [øÿ·T _Z@ ^h,h@EUÈùÖ¯€Øt@1ÁH f>œh°JDå˜ñ%ÖD\šXƒˆ×àË$Ð-@ÿŠ{Â8mX}،ݚ†1/`é`Nת4ƒøJäþ`3»® »‚©@›H#EdÖ1k}P—® âI` Koè;²ñ•€æfà4oð ï’´€œèÀ#EhéšWÞèY$êÓé$”&Ch€#^Tˆ¾8 ) ô gûXn¹–F$…VÚ¡-zøBÚ¤Þ—ƒQ0¾*¡` •¯‚)› |¹2\`îq`S{ØèÚEE÷LÀ7§è ’¦Ò ¡3`#ñò0¿d€a]@ýqBYTƒ•&Øðá"PÌAnîŽz‹ƒ'$Юl%>·‡ú€¡¶W^e¢oa„r™øùà6™ˆ w‚©Œ —(!˜<wá«_h,6»I K@<° K0ò=¥ÂÀ$i8íæ¶Ï€]W@”ˆøÍþ€') p©•0D x%±ÙW ¬OSŠ‘ì/ãòÛˆÙdž-öP‰›Ú¢? k£ò¯…ÏðAìp8~x 5O‚¤ý`“R +t:‰zàV;¨Ód’€å€1Òp ¾àKñ}‡I j*ó6ü@ µ¼;€8(–4I‹;DŠy±úñu6nW<“åƒäcÇPï'1[Y‰þJ‚©h¬XejH`ëÕP1xR p‚7Ž@x¡àªXx+?LØ i:Ï瀕!€¤ðj2Ø€8Üà Ûp}ò#hD¦&päHð&Äz¦q?¤FŠß‚‡ÄXÚ±W„CäÏífT‚Fa‰dÀ&O¾ÔóG#hcx¨ÏÀ X„;ê!8á0>$¸ |ˆJ@„‘x(J·#Ž`;Fà Þh^.u{ ¹ØÖÄ™lø€Iœ9-Ä~#•tF}ÿvºÄUq! DKÏôéD6…± lBš]‘!Ä!U1Ô@êi¥™”%¾…i>ûR?.Ë } âÀ[îÆÈæ$e™ Zzž¼v€3æ˜ Ž,©ï€CÜ /À‰UkXćA±ÌFJ\úÄJè1 dC[{´‰Ä%ŸÑ‡LAzÓFÄ iQ ¬@ëô}Ãø0ý"Œ? \$Óò†áÑï´O-ý`¡ú30M„ vÁ‚&€Y„ÐÍnXЀSô¶$JƒþüDdì‘e´C %©ÏD1,ü@luö£CõápûË<>‹ÏŽ‘Cßö¡l=p‘MCÐTpóit<¦ÝüÃÅð©¤<ø]C¥j'tÜqÌ•èiÇ•02¡Øgp.´8<‡s  |Fí“ï‹Ä‡ðþ¾Œ>`åR|CÇzï…Ô;SÕ·ýè]péÜ: csSCš¯æ"Œ9fOUIC“úðäº9%ïFCÑLPä0¼9å?ÓÃ&ðã–<8áE6+ÃŒ¼è%Ñâ uö‚ÜÊ íê0æü*GW #¿BÜ„pº6¼/=£ ì`ÚÐÁÊ„0ÕU H¥CðÇ8ü2 •äÃ*p˃œ3 Õ1C8„PÎÝì3æ¯ žCD–0ÑÀ 4Ÿ9 0cCO 0ÔL\55m WCVÓpÖ ¬5œk lxC[ì×.„3ˆE çn£Iii%Rh¨²º28B/e_Cø×›ý¤Á©ð\ÎL‚¶!BMPÁ”%!× §òB~èp¤')ú µ=¹¥ð±\Ì,ñ³ aùÂáºY/Ù ÜHÂýÆÐÀë\0j %=C ¹Pë,1k LïÃ¥ðÆü1Ÿ pWÃ;0Çä¤23 OC&G0Ê=t2¤Ñ ®‘Ã,ûÐ˃œ- XQÂÚ_·eÄ.Ñ •yBèQ°ºó”.ô¯ ÇæBõ1¾\/­7 öCupÀ¦´0L ¨CÆÃ30ï CGÃ)PÅ|1Z_ ^CÝ铊†Kˆ°CW1ì0òŸ«¸M2öZ>¾Øm/êhäű¨;@þÐÐP«<³˜½ÁÌEÐ{.” ›!Œ´Â9pP“0 %ï× ¾zB~p¢¾”)ï ^VB|0¨ÇŒ*ƒm ¶PB²h­¬¬+¸k jBÄð²¤,Ë @·BÔ3еì-®‡ xBáá°¹5<.x; ©ÛÂìàð»ãä/O Ð{BöˆÐ¾+Œ/­7 òÐÂþÙpÀ\0)­ŽÚB.,pŽD$/ )XÂR¦Ð–Š\&#U ¤ºÂp'ðÙt'Ù ñ‰簣Ñ<)R¹ iŸ0© 4*”— ¶PB²#p­›„+§? ùçÂÂð±L,›Ý 4êBÐ-дÙt-aG dÂÛ¶p·™D.; öÂåç°º<.§o ³ƒ©Hpªùi²ù:JÏ¥·º«ŽŸ#ÅáVöžè¾•£¯ÐÜ“ü5ÌñÀ‡þp3¢Lô+ÁhÃPc¥Dù-3<ÁÛpyèl;9þB ;p…,T!î) Â1dpŽmD$ Y )XÂQOp–4„& ™ÿÂm4œ×ü'”i ü´B…°¢‹(ø› QvB™1§d*)M ›}«*«Ý,+/ Úʹ갯YÔ, õ JBÆÊ²^L,ÆÉ “ àÏB{°pŸíœ(31 Ñ¿¦&Ïó {ÿ/Gè@1[Ðê´°kd@üð-w µ€ô@ôŸA·4‘Ÿ¥ÙÁ:\PRz¼‚!›ŠÁsÂ`9ÌØ%d+Á¤Ø0kÓ„œAçÁÍ0uÑD;£ãÁñŽ0~Ud Í#B!ð…ÆÔ!áI’B+9ŒjD#peò¡BAÀð‘ÇŒ$¿# D+BUš–Š\%ë‹ Œ BgMðšÃÔ&õŸ ËZ+ðê«h0"ùKtÆåû³ê-lC}OJå•£:°dîð~«Êõhؽô´ï²ÓîeúüYŠ¿ERïÛ¹{ùrþôà?ßHpŒéUñl@VèÐ;Tñ›À¶ª2Ã$ ò§ÅžApE"¬J)ÑÖÁBñTJ4ñ·®ÚÁxÛ0aômÓÁ¥êÐl¤ÕÂAÌÏ0ujLãç›NÁîšð}˜ŒÞM‹B `°„ÅT!˜U~ÂB%RpŠÎD# g×ÎÂ; P <$SÙ & ÂN\0”©´%sa lðB_†°˜Òãø¤ùæú>¯¨/¸tñ üðÑ?eÇoâÕúüìÿG|¿ðüPÁ¬³@^ô°è|ÞQŽ{@¸F2å| êÀAA:ÐDT¬¿™Á=ØðS •Áqáð_ItŠçM£Áš0j ëêHAÃõPstQýt®Áäó{.”CÏìØÂ/p‚¬ ðõRÅB—ð‡ýL"Ys«ÑÂ0 Il#›Qû6ÂCP‘û $¿# @ó-mÊKÕ› ìÊè»´—Y-•ÑÃ~ŒÜå÷:m›nÚ*[ÃÕÆóÅY=‰¯Ïs–{àÍŒùF¾};/¬.³îü2ê¿6MÏ×]³øþ’+¿ÅˆùCq¿À6¹ p ÷4À’ý°)é4 «3´ÀÞå°;á¼þ7;¢Á2Kt1ðÁS×pWú\¿µÚ×A‚>pc ÄeÅ#Á©¬0lÃܾ•ÕAÌŠutÅÛAëP|…ä„-úËBÞ‚±,! µX"Bªˆ0Ì"]½ª¿B/Èpì#ŽqôÆÂAÀîуëºûØðP8`Co£TÃë¶û‚÷?+oÊäËôï®ý½½?¾oêò3üv”ÿŠ¿ûr0Ôªs»ÀV_pŽ,áA<@¢Œ0,º4 <éN‡@âbph ¯¥ëëÈ€ûŒž¿¢ʱKô·äý­¥?ˆêoégcü JÿiÑ¿óªð¯ÓÛöÀKéÎ\,ßÀ–5°)Ø s7@ÕÇ09!ëPâ¸ÖÕ6W‹­½.Cx¦>àg¸ DnHR™£úè0øºwˆ¶Ó˳µRîM<;çÌo TÇñ2ó@=ýPÉC×ÌþöÉÓ=æ}¯…ƒäNzùÀZ¾™©¯°SîYü"Ó?)÷/Òx“ö~Êþ¤¿ @OîÄ«ý@Hÿ¯ŽÀ°0MüÝó @UÖ0©S-ì.D]ëÛ¹c ö¼Çö3NÇ-'rKT'’×|u6z%mÃ{ãyÅÆàŽ-8£|NGë™#<çÿž:g´Î²Dƒ²Ujíïå;Ìp¯ŽSÆ"ò›<åÍÏHÎ{Õ¸ÖöJ&½Å;O}¥câ6ù/ûÏ–Acè |ú–î>Égﺙkð¶6ü§Ü¿HØèƒ÷ë’þd ?±¯oòc£ýýÅà32©ÒlÑXó=äjÑÕ#5 Jíg{óbÅÊÚÞF7<›-ﳃ~Þâ³~9†®bËžÒé; º¨ŽÀ%㵄î}„;é#Ï ¦óÆü”ò»F<é¯Hx£Õk˜ö&¿=¸äÏyÒëáøï$>bhÏ¡ýsê¾lû6Ê>î°OÃQò´èýá?c¯ß$óù`îËÛ4³‰„­S³JÕzÔëÚ5È -“xëm.ÔÝE 7ËL®v›‹#Îäu9…˜Žy‰ó¤3¦êq:ð;Ïù¸´2ïM§¼ÏoãÉbFó?==™oN×sÖå@öw6½Ë!ï}”;áõ¨ù¾lUO£ÞëÖûJ>ò,ïÃÚ[òÊ\ýó³Êö;kN *Õ¦ˆµíÝÍ›– n¹¦Ý—¦7ÚÛN¾C‹}ìä|й‚îx!s£²æêAç:ázŽÌ{·”ªîþB¼žïCÇàòáå¼îOHÎ{Õ@®ö=°”/vðËàD8ø¯×>Q>/KÓéo°úàõ¾×ϽjcHß^ÔD{µ’"„„ãhÓÜ17y9mú3s…cÎâö9 ¾®`BS¿hèÉR:…¿.µHû²Àí¥Ý»®!Žû±kÂårñ¢-¼¡hO5å£Ð±bôñÁ½j’¯eùÃÜ(Ê÷­F¾z¯ðÃå»Bùõÿ¾ž}¯f«Sç2Öå.63šªgÃq¹ÖÞ2$·÷I®ÖãŒ%LäŽÈ9mNuÈ£¢ÆÞéð]:Ê$®Ä׃µ¯¸îtî»Ý›/ÁÓÅXò1ñ¼Âf=4»ÒZ>õP+½€‘/j«cÝ7(÷ç6>ŸOŸkæQv×{b6Rs °×³s/4Þt©¸²îR ŒŒJä—]9(®té{¢q éÒRº¿ónÁõc´ÌDî7Ç;Í>¯f ĺñçê<®H/8ÐúVôúV½j oe+ÃÛÆ÷>Im€)g¶Ûsg·H#Íë•;xáËÀ8ÏyNJ!{—åªçH'º!*›U³«q˜ëòF;@)àû»Ö¶ïäî¼1σɫ:ó2]<üïJ{£ÕIBõûÔ½¦ì/sbûhßèÛØA·[sï›3ô áð:¸ÕNKÓ—î>çA·º$™Ê۪߮ë˦»4å.ܶ«»l率¼ íï‚cÈœÜòèU¼é¯E…[ÔDõ«]½’E ªëpÍÎݽ37΄® ¡+ˆWão?¹/:Ž`BSœèÔèfºaDΩóã®”쨪;gR蕽»¨ðG£‹ª„ë‰!» >×7 ¹lºï:W¼± î›Æˆ¶òcL<Åâ¯<«ks|rÞO·ìJn»C‰v¦ã¡¬¹7FŽ`©SœÓ`èPºXj뭣Èì_µ»RïŽâÐ˼(@ïÛF¼)>¦3ÈüòØ=·Lnmé¬dá;ü8 Dn;ƒC“¹æ=9Ìh„«‹¥NäêU7:ÒþŽÃø[´”zîG»¶¶ÎúžÃÁÁ ñ1†¼z?M×Í;{Y.à#ö8Y¹Ž*]Fäþ\¹‡y.s++¡"éD³º‘GγW+°}Xí·;w®®ë;½æ’ð@ <>ømÜm³|Z¬àXˆ¸d¸Î,[»»°å a¹Š'îs óé; ºŒ¸Ž±ÿÓ° Äìä¿;nKn蕽C~ðë7Ô¯îž+†û€âè¹æNQùë˜ÄÒç9"ºΓIèrë ˆ:ûîÌZ#¶_¬îaž»ÊKMøÜ#‚þáæ’¸ÁËnAó;”Ðæ=9Ï[Nƒv‹¤°êüº¾œ½T벫>ív¨» müXîâj8ÊC c•®æG¼¹Ðm³¤’ê :º μòHŠí[Ö8#®ßˆÜ(ãG9#nU‡»™N&çI:º Ú.‘òk§ýˆêÛS:ë«ÎǨƒ€ËîáL¸–á.6j£‘±Ìåi¦9—ÕÎtØS ÙXéÜ:}nŽ¬Ö ®m|ìe¸žÎ£cŠ Úã…Ç9 ¾®W­ ™¬çSõ: Ú.‘zC§¸Þê¿n:ãn Žƒ†”‚â¨Ã¸èônI©S–/ìæx9×"ŽƒÌ[¤Q°éçǺ¬è. ¤#‡;àâ˸ð»ÎK"û–xâæ…ö¹ÙNƒî³¤Mféâj¸}ª®.ų{PäÉÊ9kØÎi ¶ÒèB#:D‘®!åËŒ? ãù¦¹8Y.\šqúçs:›n‘CŒÄäž9=¶n],«š²Xç{§:in4ðûÅÂåt9yBkužˆäK0¹Hq_…{›äg¹NW®`d£›DBåO湆fŽV3`ÎZµ¦¥k%ê­&<¥æÅu%F%»€å£EÜ¥å%Ô¥©¦¦Æ‹¦}æef,†&K(†ÄkyfMƱFd& ÆfÆ¦Öæ¨Ê´ ¯†ªf(f&Y¥÷¦Yf`¦ƒæPf£&d *7ŠQj>ä…Ù%ÜF0†]&f!&afå§浉ɒéÖ‰Þ)óêêF^æ%§f5%Óf2&ZFžfÃæ¼§'æáÇ¥¨Q),Iˆ·HçÉYiɃIµ ÷Š!*IÆ Ý彆0fHæ•'IÆi&—F—'.ÇB'’ÈZ§ñȇ¨RÛˆC¨{H›èÝÈûˆ•ȹ ˆÿé‰Yi]‰e©¯* êAÊcåÈeó¥þ†X†{fXß&Ó‹æïFß§Cç·F¬Çqg·è`è çûçéhbÉhÌHŸˆ½è¸¨ý)eÉ„)Œ ¶içJ 5ÅʆNeöÆS¦fÙF_çg ff“e»Æ¤…æF¯Ç g‘ç©§¶çš§îèÁi ëÈ¢HeH¸)G))‰i™©¡‰· ó&©e›†ªeìf–fÂJ E´†¿æ¯ÅÁ'o†üÆ['!§…‡«GC‡U…Gæ¨~ˆ‹èšˆÂèÀ(äÉi .éb‰€i™‰Õ Å›ævEîfÆó…­ØfðæDÇ-e»†‡£>'mÇbG@ç3§bG¨Çžçw(hM(Ih¸é©'‰*ˆäèÆiiC‰v©¿)õ¸¦¾FOÇëg[&2J‡ªÆf°t‡iÇKǘÇ^GS§‹G¼GÕG‹gœ¨ (YÈkˆ{hà)?ɨ¶(ªèЩé’©ò…F…¢fÝ¦ðæ›Æ6Gßþ%®ç²&ÄfòFãÛ&à‡X§?]Œ‡æGîçù‡¦Góh9(Rh¼©+©2þHÒȾæI\éÊ)éì ˆdÓFI…9d˜Ç6Æ2tF ¦dƹfÍg^‡'‡ FøG!‡Y§tGØg ‡Äg®Ç¡¨ÈDè©(öI .‰1i ©)@é~‰‹ÿÿê¶æD§Õ¥yFÔg¦V†¬&e¦Ü¦Ó‡¦ñƇfÇ'+§8çk‹ç‚¹çÀÇ GÒH Gãè7À¨ðÉ É:)I iFÉd‰^ ªH‰€ˆŽ…NEè'ž†{Æ]f’FÖ¦æ‡g ú¦åç;G§‹‡¤çˆÇʇ÷‡Â( Göè"‡(„ȹÉHóèðÉ+éAÉFéË'DHDÇ„ú%1ªf†kÆäFÆgØÆÁ&ÄFíÆ²F†&âGJç%ç‡BgyçˆGùGº'ôˆ (Haˆ4HGȳhÛÈîÉ Èÿ‰‰Ô«PÆVeÆ2'ù††JÆô…†pðf’Ưf¥Ç Æ©F²gÆáLJDžç®ÇÇGvgÓè%((BÈCÈIH_(pH¹‰èúˆüé±+¬¯ÌLÍç6%E Åç¦Ú…hE‚f†Æ‘&k&þg&çÀ†»æÁç2ÇgX§/‡z§ŠçÕgí§¿‡òHè gæè$HnhZH‡èò) ‰wÊm Èlˆ¬¼ˆYåèÆE%ª¦˜†'r¦$Æ2†´æ€fà&ÃÆïÒ'†Òg'C‡Z'ÆÇÅgà‡éÇõGßè(ÈÈp¨o(€HÉÈÏÈÁÉ ‰¦jžÌìïÌ9ͧ†’fRÆ©fž¦öÅÞwÆWF”Æ‚­ÀæŠæ‘ƯFùFægg4Ç’‡œ‡zgãHÈH è(ÈoèkȃˆÌH¿HŒ·i" ­ÊºL^ ; ‰ ]çh¦b%ò¦Ƥ&Îç3EŽ&ÁNFüæífŽF|ÈÆÂfÚfÞg/ÇY'ǧ©‡æ(gë§õlH„“ÈϨÌÈ®HÔ)I: ¾ ,À,í¦±†u[† ¦’f.æÀç?Df'†„&äF~Á¨F´î¦î¦ðüg€§|Ç©¤‡Ñˆ 'õˆ2¨J¨yãêÈÏ )Q‰` *:Ë,挊æð!æ£Æ—F‡¦ÞF(F½æyfåÆœËÆÒfµ f÷'@.'4'dG]'ÒGùèè(8Èeh„hò© èÞñÉ6éoé¦Ê ë@«êgìæÍÆÚærf*†o¦˜f ÇHf;ÆJ'1fÃ&éFÐ&ã†Þ†õ'<íüî¤nŽŠî›Ž_mìM¯-ÀMÊm­­›ºííÎmímÒÍË ÖMå­ñ-ûNÎî3.@Î?n2Î*N0îCÎV®]nUC,nn-ú-üŽ &nDÎaÎxN‡ŽŽÎ’N“®•ΜN¤Î¯Ž¸î½Î»J†jñ‹Ãl{Í9Ž?éîº._®bjníºm¦-Ô-èmÒÍÒ.1./N­üŽ.NN#ÎO®ˆÎ­.¬N….VŽ<îCÎ`nzînrNRî0®NÎ n®6NTŽiÎtnsîmne®bŽgtnˆŽŸîµîÅÉN¿%ž¥üæ±×CFû¦ÜFT'lç:'£)½Œm|*Ž...ÎxNÅÅî^Nn ë­¼mÈN.&n)Ž6.\NrNc®JŽFNSîVŽJ.C.ZN“ÒŽö.鎶Ž~]ÎbNzŽŽ”‚.cnCî-Î*î<®\Π.®îªî™Î…ntNnÎx.Nª®Ë.çø.÷ÎåîÂ)zI¥)Ê"j•ë NMÑ%O®QnZ®—®¨î™Qî mä­êMùíöíýN#®O.eNlîpNnnjon~އ~nl®f®zn¤Ñ.ìNæîÇ¡.‹ˆ®’ÎNžn”.‚mîb®e®z›îÀîÝ.çîàîÏŽ»N®Î¯¿Ùüï¯;/IDÏ*õ&‘&.'…¼F8æƒÇÄ©rj/jÂËn̬L,m Ñ-í­K¯‚®ÜNFîŸn±îªÎ·î’Ž:M÷î.P.[;®:Ž[Žr.dŽEn8®PŽ|.›.œ‡®qngÎlz.î¨n¸½N¸®°.§®¢Ž¡Î¥.©ŽªN¦î¢¢N­Á*“«gKöŒÄ 6ín-àîÍÑ­®Í•,Û¬Ï N‘αÎñîµn®nËŽµNhÎ;nnŽº®·Îy.Z®k®xN[N/Ž)®Xî—î¶Žª.‡Nh®TNFŽ?®HÎdŽ®³ŽÉîËN½ÅÛ¥¾Ær&¦b'óhæªB AÍnwí´Ž9NPŽXn¦k-Äíš­kLx¬PmhÄíénun}n].NÎŒN€Ž‡Ž¼®îŽÚN›®wÎîŠNvn[.a®’ÂîÏÎ³Ž‡®bG.2Î'n0ÎU «Ì1ígNt’.FNXŽ¢N¯£î…."-Ømß-‘ Äl,œ ÁvåmåN"ŽG®;NdN§NÈÕîÚ.ÁΔÎvÎz®nš®š£n»NÎÎÈΨ®.]ŽHæï匦Xñ»éò F ¹=¢®Á.ªNtŽvŽÊ®ò.šî<îENSîMŠí¬ˆLPmmø. Ž#h.H1N‘Žõ®ú®ÐNµN¢NZnX.zΣN´.±Ž«î¨®¡Ž‹Ë4,ð®&nžNÓŽ³n¬Âî’.¥¯ ¯.c®!ŽˆÎiM³íP-L` œÍꎊN.ÎÎÈÎl®vNô>ïnÌŽ«NŽyŽI=eîœî²Î¡îˆÖHÝJ Œo-©N6ŽqNÛŽûn¾.ÙnÓN¹òo<®ß®®Nt-ÿíM­,,Ô Tí® ÎPNšîÙN”cN³*¯EON»Î .œ†.^Pnt®­®È+¶M ŽY®2®kNì®Öîª.î…ξNÂŽµ®inN ®Mƒ,ülî,¯,½mx-Æ-æ8.M׎-.¯OîÂNniŽ{î“.î‡Î¢. ®KÎÎަ®ÎNwNí±.-.yn Ž.ÎUî à­¸ %  ¬›¬× z çÍ÷ÍÙ H iÎ8ÓnôŽÈ΀.7îŽLî›îÁ°Íº®~.ý®¦N&mN Aî<î1 ÎN>.„®-»í›ÍŒu¬–m?ÍúŽmòkM­Ê¶¯Îùν.nî­ý®B®­­¯É.ÈŽƒ-øm´nz®-÷n†ÎšÎÍÜmÂÍ#Œ·Í -¸îݬ :¬©M;΋/AïHï®ÎG5N-ùN4m¾Íxn/nHMü®=N¤.ŒŽ&έò­€Íp Ò®A.DíØm î ïmx.ë/NO(îén·®› È­í£-—-Í ñ­ÕîWÎxŽgÎ;NE.9®Un“®º.¨n Œ«U, ÇN¯î®¢.jîN¬c m•ºMŠæ®D)îÍ…Mö0NuŽÐN Mÿ k [í° ÿ–nànÍ‘íYMomªzCM™ÍX JM_MË­r­A 3 Ímˆ­> 5­²m\-èâ!.§Ke”èk².†³nªk1VÊtÒ=¬ÅZ©“Ä ¬ÅZ)RÈ“ñÐØ@ µ˜«E"U{8š %±Øðz>b,ÔI41äÜe.•б Ôl7GL5Š…$„;› E¢‘,ŒA…âñxÀb2£qÂÁ@AF¹<ŽAŽ£p°V* EB¡P¨T+ EÂñ€Èf5X'Ñè¡ ¼T&àÀX)‰D¢A J% „âH¨V- +ú=r3ÊD’ìj0‰Ä‚€>ˆF% Å"¡`¹n¡GŸÎ&RÑ@Ž? …‚q|: †Ãa°Øp:Ä"!”N)‹Wêt’âd,ˆ£Ñ°¼R$†Ãp°X, †Ðl:„‚a@©Ž¯L¡F2¹4†;‹Dâ è`* ‚A ˜L( Ã!°à|B#Š u(ìe+“C‘ˆ¨H …‚ax8ƒÂP* †Ã”NÙ_©Ò'ÃId˜A "0èd(€°X, ƒ‚  X0ˆBW\˜A‹¤ÒÜ^'‡á0x0 Àà€@( Ba`Àl< ‰¡nÆzÙ>‰:˜Š$1À¸L …‚ ÐP  P0  aPÀl `€0€À`@( „a`Àl"‰®ÖzÕ<‰:˜ÊD1°¨@  P€@  ‚ÁÁ \4„‚FÒùL>‹$¡Ø¼F ƒ `‚A€ðP.ˆbQ •ÌÉW¦P‡#D„5‡‚ÁP€À€X4  aá”L%µ—j4qìÒY%â@ØL€ €@@0( „BpÐt@# ÙKÒäb)±\ À €@@0( a`Àl Äâ¡X´^0ÂL( †! àt>  ¢P°Z/Œ†‹å:Dük-“HAP„4€àP €àX0„! ˜P* †CA°èx>! ÂqH¨X.ŒFcA° ‚  `4BA0 T, †ƒaÀè|@"‰DÂH¬X. FcA°án FLå‚Xøh*¡`$€àp8  ƒ àx@$ BÁpÀd4CˆH%ŠB±h¸`2FÃÈ ‚A@°`4„‚a@¨X. †ƒaÀèx@!Ä¢a8¤T,‹Æ!˜Ôn8ÙK$â ìf+’‡ãQ`: Á€°P( Á`Àh8„‚a@¨X. †ƒaÀè|@!Ä‚a8 T+ …ãÐj7އƒÑø4 €Àh4BA@¨X. †ƒaÀèx> ˆ„bA(œP) ¢ñ€Äf4 Ç#¡àô~@c+Ó(c©”®J…Â`øh, Bðx8ÁáˆH& …‚á€Èh6‡ƒâˆF$‰Å‘P¬Z.ŒFC1¨Øp9Ãò . ÂA ˆD B! ˜P* A Øp:ˆ"!L' EB±`¸^0ŒÆƒQ¸àr;‡ä¸ÃV%Ї3X”A Å0ðp4 ÂÁP L& Âa@¨X. †ƒaÀèx> ˆDbA(˜N(Š…bÁp¼`1 Æ£a¸ät;ˆŒGˆ„!ðèp4 Âá`¨T* …‚á€Èh6‡ƒâˆF$‰„âH¨V- ÆÌh6Ž#±àô~@!È„b9%²ÀT¥GXšDŒÅ‚¡8”F!áÀØh2 …ÂápÀd4CÁðø€B"‰¢a8 T+ EÂñ€Äd3 FãÈèv=È$"ŒH$’‰„Rðr5 Å‚¡@˜J#ˆáÐàl6 ƒA Øp:ˆ"!J&Š"¡X°Z.ŒC1 Ôl7GC±àô~@ È„R9 ’K&ž Uê&8™ %R,ŽCÇQ¼Z+ŠÂA„@C¡Ààt:ˆ"!ŒH% Å‘P¬X-Œ#!˜Ðj6Ž#£1„¸W)I$Røt8ŒÆñh¬R' b!€@ˆŒF$‰„âH¨V,‹…ãˆÉÚÓ]©’h#ÙÐÜh1—‹%By,ŽD ‡c°Ðd0 B‘8˜J$ˆÄB!ŒH%‰„âH¤T+ EÂôZúv8ÌÆÙ\¤N%È„ððt7ŒÆ"ñh°T) ÄÂa0˜L&Š‘P¨V,‹¡¶’íN•F¡ç“™¸Òc/J¥i(ŽD!Ç£±ÈØh2‹ÅÂÁX¨T)ŠE"¡P¬V, Eʺ=‚>Ž&³1„¸X*IIJA†AC°Ðd1 ÅÂÑh´Z-‹EÂá{Iz³U(S)$Zþy9›2ùl®T(“‰d’1„?ŽÇ#°Ôf3 F#€À`0¯ÖªÅq*D ‡c¬Ìb/ËR‘<˜J#‘Hdøôv: ÆÃa¨Ôh4 êå2}0’E¡Oç“™¸Ôf1Ëe‚±L M%’ÄB~>ÇC¡Èàp7XªTI´ª9‚>Ž&ÓI˜Ä_.JÅB‰8˜J$ˆ¤2~>GƒÅb•<˜H¢Ð§óÑÔâm5Ìféh®U) ÄÂQ$ŽF"‘d" ¥D›J#‘#éäêq7ŒæC x¶X+ Eq4–J$’êÅ*y.‘E¡'ÓÉÔän5š †ùp´X+ E8šLT(SIDz) >žNÇ#y¬Ðe1 ÅÂÑ`®U*Š*µ"y0“G"P¨ñèìs7› &c!ˆÀ^.Ë%‚ºBœK¤‘È”*üz;œÎÓQ Ìd1KååZ•@›K$‘Ȥ2üz;&ãa¨Ðf2˜Õê•"}4–I#‘Hdøöx:œÎãa¬Ò³VªiôÒY$ŽE!Góáäîu9œMëu’µP£O&’Éj) ƒ@Og“¹Õl±V)ÔIäÒU"ŽE!Ј#ùôöºZ¬jeu2•H£‘h„2¾\­ê¥*…:™J¤‘èÄR!„½\,ÕÊ•*…:™K$Ò(ö3x·Y+U*U u4˜J¤ÙLVíl±VªTª$úq4Îd±륲ÅZªS(Ô-6k!†¿]-–JåZ¡¤Íd0×Ë¥²Í`Öh³ì5úípµk4YŒ†#zÚj´Y¬–3i¬Òg7Ûmv£ºæ@˜ @   @ A €@ H  ‚@€@H$ @ € ‚C€@$ €@ € €!‘ˆà2 †C!€À$ @!ˆ@21 F#€ÀB€@ €B D"`$€ €D †FˆÀ`0D"„B!”J,‚ D „!ÈÀ`1"€B!D„H$‰€Ð@„!€D  Œ"„@!ˆD€@ ‰D‚A H, B€@"„ÈÀ@!ˆ"„@ D¢A H%‰‚Àè@" B€@ €B!" J%‰D‚Q(H$‡!€D0@H B ˆ"„J$ D‚A ”J$ D¤,BH"„B! D‚A(H%‰D‚Q€B!D €è\(€ €J% D¢A(”J%ˆ„B E@¨T"@ P ˆ¢A(”H% D‚A€@!ˆD"„@ ˆE!@¨P @„J% ¢A ”H%ˆ„@!D€@! €@T*!Pè0%‰D¢A(”@ €B „@ ˆD"H *CШT  D‚„@!ˆ"„@!ˆD„@ D"H R ŽA Ð T( „B ˆ€B ˆ€@ "€B)ŠAÀ(„B!ˆ @ ˆ„@!ˆ"€@!ˆD„B  A €(€B!€DP!D€B!ˆD"„@ ˆ€@ ˆE€@ €@€D0!ˆD„@!ˆD"„@!ˆD„@ ˆD"@$@"ˆ"„@!D"„@!ˆ"€B!"@$B!@ @„G„B!ˆ"€@!"€@!ˆD„B!ˆD"€@(D"„@ D"„B!ˆD"„@  €@@D00ˆD"€@!D"€B!ˆD„B „B!„B!ˆH¤ €@!ˆD„B!„B!ˆ€B!ˆ¤R @€@ Ž#„@!€@ D"€B!„B!„B!€@ H¤!ˆD"„B!ˆD"„B „B!"„@ €@ ŠE €H $b1 D€B!ˆD"„B ˆD"„B!ˆD"„B!ˆD"€@!ˆD€@ "‘H¤!€@!ˆD„B!"„@ D"„@ „@  ‚ €H0 ‚"ÀÀ`0D„@ €B!€@ D"€@ ˆD"€@ "$D€@ "€B!ˆ„@ D"€@ "„@   @ @Àäb!"€B!ˆ€@!ˆD„B!ˆ„B!€@C#ÀÄ@ ˆD"„B D"€B!ˆ„B "„B €   !€D0 E€@ D"„B!€@ D"€@!€@ €@ A H$€È„ˆD" ŠE"„B D"„B!"€@ ˆD€@ €@ ‚A @ A H$ €@€P( ˆD „BH¤P!ˆD„@ ˆD"„B!ˆ"€@ H$ ‚A„ˆ@ ‚E‘„@ ˆD„B "„B‚A H  @€@@ €@"@ P(€@!ˆD„BH$€@ 4 D"„B!€D  "€B!ˆ€@ ‚€H$€ @ B!€D"„@ @$R)"€@!‚A€H€@ P 0@ !ˆD"€ ‘H @!ˆDH$ @ €À(@ B!€‚A„B A€H €@h4€@„B!ˆD €@ P( A@ €@Ðh€@„B!ˆD €@$( @€@(€@@ B!ˆD€@ @$ €AÀ @B€D €@ $ ‚A @(€@B€D @ €H$  P  @ "!ˆ@ ‚A € @ €D"„H  P € €`0 €P  @„Àd@ @(€"H  P@ ˆD" @ „B!À €@  @0@ @ €@ ‚@ P    ‚@ P    À€P  @ $€P €X  ‚ÁàP H, P ƒ@€@(A À   Ð  A€À  A À`4 ƒ7777BUFRU¬b€Ë 4Ë~hd!]ò}L!Øb¿°V@ܼ.ÿÿdE¤F ¼ÀÌFUL €(!I¸¾@@@ @ €€€ € €@€@À À À@À@À`Àa!!AAaa¡¡@!@!@A@A@a@a@@@¡@¡@Á@Á€!€!€A€A€a€a€€€¡€¡€Á€Á€á€áÀ!À!ÀAÀAÀaÀaÀÀÀ¡À¡ÀÁÀÁÀáÀáÁÁÁ!Á!ÄaÄaÄÄ‚BBbb‚‚¢¢ÂÂââ""BBbb""BBbb‚‚@B@B@b@b@‚@‚@¢@¢@Â@Â@â@âAAA"A"ABABAbAbA‚A‚A¢A¢CâCâDDD"D"DBDBDbDbD‚D‚D¢D¢€b€b€‚€‚€¢€¢€Â€Â€â€â""BBbb‚‚¢¢ÂÂââ‚‚ƒbƒbƒ‚ƒ‚ƒ¢ƒ¢ƒÂƒÂƒâƒâ„„„"„"„B„B„b„b„‚„‚„¢„¢ÀbÀbÀ‚À‚À¢À¢ÀÂÀÂÀâÀâÁÁÁ"Á"ÁBÁBÁbÁbÁ‚Á‚Á¢Á¢ÁÂÁÂÁâÁâÂÂÂ"Â"ÂBÂBÂbÂb‚‚¢¢ÂÂÂÂÂâÂâÃÃÃ"Ã"ÃBÃBÃbÃbÂÂââÃÂÃÂÃâÃâÄÄÄ"Ä"ÄBÄBÄbÄbĂĂĢģccƒƒ££ÃÃãã##CCccƒƒ££ÃÃãã##CCccƒƒ££ÃÃãã##CCccƒƒ££ÃÃãã##CCccƒƒ££@c@c@ƒ@ƒ@£@£@Ã@Ã@ã@ãAAA#A#ACACAcAcAƒAƒA£A£AÃAÃAãAãBBB#B#BCBCBcBcBƒBƒB£B£BÃBÃBãBãCCC#C#CCCCCcCcCƒCƒC£C£CÃCÃCãCãDDD#D#DCDCDcDcDƒDƒD£D£DÃDÀƒ€ƒ€£€£€Ã€Ã€ã€ã##CCccƒƒ££ÃÃãã‚‚‚#‚#‚C‚C‚c‚c‚ƒ‚ƒ‚£‚£‚ÂÂã‚ッƒ#ƒ#ƒCƒCƒcƒcƒƒƒƒƒ£ƒ£ƒÃƒÃƒãƒã„„„#„#„C„C„c„c„ƒ„ƒ„£„£„ÄÃÀƒÀƒÀ£À£ÀÃÀÃÀãÀãÁÁÁ#Á#ÁCÁCÁcÁcÁƒÁƒÁ£Á£ÁÃÁÃÁãÁãÂÂÂ#Â#ÂCÂCÂcÂcƒƒ££ÂÃÂÃÂãÂãÃÃÃ#Ã#ÃCÃCÃcÃcÃÃããÃÃÃÃÃãÃãÄÄÄ#Ä#ÄCÄCÄcÄcăăģģÄÃÄÄ„„¤¤ÄÄää$$DDdd„„¤¤ÄÄää$$DDdd„„¤¤ÄÄää$$DDdd„„¤¤ÄÄää$$DDdd„„¤¤ÄÄää@d@d@„@„@¤@¤@Ä@Ä@ä@äAAA$A$ADADAdAdA„A„A¤A¤AÄAÄAäAäBBB$B$BDBDBdBdB„B„B¤B¤BÄBÄBäBäCCC$C$CDCDCdCdC„C„C¤C¤CÄCÄCäCäDDD$D$DDDDDdDdD„D„D¤D¤DÄDÄDäDä€d€d€„€„€¤€¤€Ä€Ä€ä€ä$$DDdd„„¤¤ÄÄää‚‚‚$‚$‚D‚D‚d‚d‚„‚„‚¤‚¤‚ĂĂä‚䃃ƒ$ƒ$ƒDƒDƒdƒdƒ„ƒ„ƒ¤ƒ¤ƒÄƒÄƒäƒä„„„$„$„D„D„d„d„„„„„¤„¤„ĄĄä„ä……ÀdÀdÀ„À„À¤À¤ÀÄÀÄÀäÀäÁÁÁ$Á$ÁDÁDÁdÁdÁ„Á„Á¤Á¤ÁÄÁÄÁäÁäÂÂÂ$Â$ÂDÂDÂdÂd„„¤¤ÂÄÂÄÂäÂäÃÃÃ$Ã$ÃDÃDÃdÃdÄÄääÃÄÃÄÃäÃäÄÄÄ$Ä$ÄDÄDÄdÄdĄĄĤĤÄÄÄÄÄäÄäÅÅEEee……¥¥ÅÅåå%%EEee……¥¥ÅÅåå%%EEee……¥¥ÅÅåå%%EEee……¥¥ÅÅåå%%EEee……¥¥ÅÅåå%%@E@E@e@e@…@…@¥@¥@Å@Å@å@åAAA%A%AEAEAeAeA…A…A¥A¥AÅAÅAåAåBBB%B%BEBEBeBeB…B…B¥B¥BÅBÅBåBåCCC%C%CECECeCeC…C…C¥C¥CÅCÅCåCåDDD%D%DEDEDeDeD…D…D¥D¥DÅDÅDåDåEEE%E%eEeE€e€e€…€…€¥€¥€Å€Å€å€å%%EEee……¥¥ÅÅåå‚‚‚%‚%‚E‚E‚e‚e‚…‚…‚¥‚¥‚łłå‚僃ƒ%ƒ%ƒEƒEƒeƒeƒ…ƒ…ƒ¥ƒ¥ƒÅƒÅƒåƒå„„„%„%„E„E„e„e„…„…„¥„¥„ńńå„å………%…%…E…E…U…U¥E¥E¥U¥UÀ…À…À¥À¥ÀÅÀÅÀåÀåÁÁÁ%Á%ÁEÁEÁeÁeÁ…Á…Á¥Á¥ÁÅÁÅÁåÁåÂÂÂ%Â%ÂEÂEÂeÂe……¥¥ÂÅÂÅÂåÂåÃÃÃ%Ã%ÃEÃEÃeÃeÅÅååÃÅÃÅÃåÃåÄÄÄ%Ä%ÄEÄEÄeÄeąąĥĥÄÅÄÅÄåÄåÅÅÅ%Å%ÅEÅEÅUÅUÅeÅeåeåeåuåv¦¦ÆÆææ&&FFff††¦¦ÆÆææ&&FFff††¦¦ÆÆææ&&FFff††¦¦ÆÆææ&&FFff††¦¦ÆÆææ&&FFffvv††%v%v%†%†@Æ@Æ@æ@æAAA&A&AFAFAfAfA†A†A¦A¦AÆAÆAæAæBBB&B&BFBFBfBfB†B†B¦B¦BÆBÆBæBæCCC&C&CFCFCfCfC†C†C¦C¦CÆCÆCæCæDDD&D&DFDFDfDfD†D†D¦D¦DÆDÆDæDæEEE&E&EFEFEfEfE†E†E–E–e–e–e¦e¦€Æ€Æ€æ€æ&&FFff††¦¦ÆÆææ‚‚‚&‚&‚F‚F‚f‚f‚†‚†‚¦‚¦‚Æ‚Æ‚æ‚æƒƒƒ&ƒ&ƒFƒFƒfƒfƒ†ƒ†ƒ¦ƒ¦ƒÆƒÆƒæƒæ„„„&„&„F„F„f„f„†„†„¦„¦„Æ„Æ„æ„æ………&…&…F…F…f…f…†…†…¦…¦…¶…¶¥¶¥¶¥Æ¥ÆÀæÀæÁÁÁ&Á&ÁFÁFÁfÁfÁ†Á†Á¦Á¦ÁÆÁÆÁæÁæÂÂÂ&Â&ÂFÂFÂfÂfÂ†Â†Â¦Â¦ÂÆÂÆÂæÂæÃÃÃ&Ã&ÃFÃFÃfÃfÃ†Ã†Ã¦Ã¦ÃÆÃÆÃæÃæÄÄÄ&Ä&ÄFÄFÄfÄfĆĆĦĦįįĿĿÅÅÅ&Å&ÅFÅFÅfÅfņņŦŦůůÅÖÅÖåÖåÖåæåç''GGgg‡‡§§ÇÇçç''GGgg‡‡§§ÇÇçç''GGgg‡‡§§ÇÇçç''GGgg‡‡§§ÇÇçç''GGgg‡‡§§ÇÇçç÷÷&&A'A'AGAGAgAgA‡A‡A§A§AÇAÇAçAçBBB'B'BGBGBgBgB‡B‡B§B§BÇBÇBçBçCCC'C'CGCGCgCgC‡C‡C§C§CÇCÇCçCçDDD'D'DGDGDgDgD‡D‡D§D§DÇDÇDçDçEEE'E'EGEGEgEgE‡E‡E§E§EÇEÇEçEçFFeWeWegeg''GGgg‡‡§§ÇÇçç‚‚‚'‚'‚G‚G‚g‚g‚‡‚‡‚§‚§‚ǂǂç‚烃ƒ'ƒ'ƒGƒGƒgƒgƒ‡ƒ‡ƒ§ƒ§ƒÇƒÇƒçƒç„„„'„'„G„G„g„g„‡„‡„§„§„DŽDŽׄׄç„ç„÷„÷……………'…'…7…7…G…G…W…W…g…g…w…w…‡…‡…—…—…§…§…Ç…Ç…ç…ç…÷…÷†††††'†'†7†7¤—¤—¤§¤§¤·¤·¤Ç¤Ç¤×¤×¤ç¤ç¤÷¤÷¥¥¥¥¥'¥'¥7¥7¥G¥G¥W¥W¥g¥g¥w¥w¥‡¥‡¥—¥—¥§¥§¥·¥·¥×¥×¥ç¥ç¥÷¥÷¦¦¦¦¦'¦'¦7¦7¦G¦GÁGÁGÁgÁgÁ‡Á‡Á§Á§ÁÇÁÇÁçÁçÂÂÂ'Â'ÂGÂGÂgÂg‡‡§§ÂÇÂÇÂçÂçÃÃÃ'Ã'ÃGÃGÃgÃgÇÇççÃÇÃÇÃçÃçÄÄÄ'Ä'ÄGÄGÄWÄWÄgÄgÄwÄwććėėħħķķÄÇÄÇÄ×Ä×ÄçÄçÄ÷Ä÷ÅÅÅÅÅ'Å'Å7Å7ÅGÅGÅWÅWÅgÅgÅwÅwŇŇŗŗŧŧŷŷÅÇÅÇÅ×Å×ÅçÅçÅ÷Å÷ÆÆÆÆÆ'Æ'Æ7Æ7ÆGÆGÆWÆWãçãçã÷ã÷äääää'ä'ä7ä7äGäGäWäWägägäwäwä‡ä‡ä—ä—ä§ä§ä·ä·äÇäÇä×ä×äçäçä÷ä÷ååååå'å'å7å7åGåGåWåWågågåwåwå‡å‡å—å—å§å§å·å·åÇåÇå×å×åçåçå÷å÷æææææ'æ'æ7æ7æGæGæWæWægæhhhˆˆ¨¨ÈÈèè((HHhhˆˆ¨¨ÈÈèè((HHhhˆˆ¨¨ÈÈØØèèøø((88HHXXhhxxˆˆ˜˜¨¨¸¸ÈÈØØèèøø((88HHXXhhxxˆˆ˜˜¨¨¸¸ÈÈØØèèøø((88HHXXhhxxˆˆ#È#È#Ø#Ø#è#è#ø#ø$$$$$($($8$8$H$H$X$X$h$h$x$x$ˆ$ˆ$˜$˜$¨$¨$¸$¸$È$È$Ø$Ø$è$è$ø$ø%%%%%(%(%8%8%H%H%X%X%h%h%x%x%ˆ%ˆ%˜%˜%¨%¨%¸%¸%È%È%Ø%Ø%è%è%ø%ø&&&&&(&(&8&8&H&H&X&X&h&h&x&x&ˆ&ˆ&˜&˜AhAhAˆAˆA¨A¨AÈAÈAèAèBBB(B(BHBHBhBhBˆBˆB¨B¨BÈBÈBèBèCCC(C(CHCHChChCˆCˆC¨C¨C¸C¸CÈCÈCØCØCèCèCøCøDDDDD(D(D8D8DHDHDXDXDhDhDxDxDˆDˆD˜D˜D¨D¨D¸D¸DÈDÈDØDØDèDèDøDøEEEEE(E(E8E8EHEHEXEXEhEhExExEˆEˆE˜E˜E¨E¨E¸E¸EÈEÈEØEØEèEèEøEøFFFFF(F(F8F8FHFHFXFXFhFhFxFxFˆFˆF˜F˜F¨F¨c˜c˜c¨c¨c¸c¸cÈcÈcØcØcècècøcøddddd(d(d8d8dHdHdXdXdhdhdxdxdˆdˆd˜d˜d¨d¨d¸d¸dÈdÈdØdØdèdèdødøeeeee(e(e8e8eHeHeXeXehehexexeˆeˆe˜e˜e¨e¨e¸e¸eÈeÈeØeØeèeèeøeøfffff(f(f8f8fHfHfXfXfhfhfxfxfˆfˆf˜f˜f¨f¨f¸f¸ˆˆ¨¨ÈÈèè‚‚‚(‚(‚H‚H‚h‚h‚ˆ‚ˆ‚¨‚¨‚ȂȂè‚胃ƒ(ƒ(ƒHƒHƒhƒhƒxƒxƒˆƒˆƒ˜ƒ˜ƒ¨ƒ¨ƒ¸ƒ¸ƒÈƒÈƒØƒØƒèƒèƒøƒø„„„„„(„(„8„8„H„H„X„X„h„h„x„x„ˆ„ˆ„˜„˜„¨„¨„¸„¸„ȄȄ؄؄è„è„ø„ø……………(…(…8…8…H…H…X…X…h…h…x…x…ˆ…ˆ…˜…˜…¨…¨…¸…¸…ȅȅ؅؅è…è…ø…ø†††††(†(†8†8†H†H†X†X†h†h†x†x†ˆ†ˆ†˜†˜†¨†¨†¸†¸†È†È†Ø†Ø£h£h£x£x£ˆ£ˆ£˜£˜£¨£¨£¸£¸£È£È£Ø£Ø£è£è£ø£ø¤¤¤¤¤(¤(¤8¤8¤H¤H¤X¤X¤h¤h¤x¤x¤ˆ¤ˆ¤˜¤˜¤¨¤¨¤¸¤¸¤È¤È¤Ø¤Ø¤è¤è¤ø¤ø¥¥¥¥¥(¥(¥8¥8¥H¥H¥X¥X¥h¥h¥x¥x¥ˆ¥ˆ¥˜¥˜¥¨¥¨¥¸¥¸¥È¥È¥Ø¥Ø¥è¥è¥ø¥ø¦¦¦¦¦(¦(¦8¦8¦H¦H¦X¦X¦h¦h¦x¦x¦ˆ¦ˆ¦˜¦˜¦¨¦¨¦¸¦¸¦È¦È¦Ø¦Ø¦è¦èÁ¨Á¨ÁÈÁÈÁèÁèÂÂÂ(Â(ÂHÂHÂhÂhˆˆ¨¨ÂÈÂÈÂèÂèÃÃÃ(Ã(ÃHÃHÃXÃXÃhÃhÃxÃxÈÈØØèèøøÃÈÃÈÃØÃØÃèÃèÃøÃøÄÄÄÄÄ(Ä(Ä8Ä8ÄHÄHÄXÄXÄhÄhÄxÄxĈĈĘĘĨĨĸĸÄÈÄÈÄØÄØÄèÄèÄøÄøÅÅÅÅÅ(Å(Å8Å8ÅHÅHÅXÅXÅhÅhÅxÅxňňŘŘŨŨŸŸÅÈÅÈÅØÅØÅèÅèÅøÅøÆÆÆÆÆ(Æ(Æ8Æ8ÆHÆHÆXÆXÆhÆhÆxÆxƈƈƘƘƨƨƸƸÆÈÆÈÆØÆØÆèÆèÆøÆøã8ã8ãHãHãXãXãhãhãxãxãˆãˆã˜ã˜ã¨ã¨ã¸ã¸ãÈãÈãØãØãèãèãøãøäääää(ä(ä8ä8äHäHäXäXähähäxäxäˆäˆä˜ä˜ä¨ä¨ä¸ä¸äÈäÈäØäØäèäèäøäøååååå(å(å8å8åHåHåXåXåhåhåxåxåˆåˆå˜å˜å¨å¨å¸å¸åÈåÈåØåØåèåèåøåøæææææ(æ(æ8æ8æHæHæXæXæhæhæxæxæˆæˆæ˜æ˜æ¨æ¨æ¸æ¸æÈæÈæØæØæèæèæøæøçççç©©ÉÉéé  ))IIii‰‰©©ÉÉéé  ))99IIYYiiyy‰‰™™©©¹¹ÉÉÙÙééùù  ))99IIYYiiyy‰‰™™©©¹¹ÉÉÙÙééùù  ))99IIYYiiyy‰‰™™©©¹¹ÉÉÙÙééùù  ))99IIYYiiyy‰‰™™©©¹¹ÉÉÙÙééùù  ))"Ù"Ù"é"é"ù"ù# # ###)#)#9#9#I#I#Y#Y#i#i#y#y#‰#‰#™#™#©#©#¹#¹#É#É#Ù#Ù#é#é#ù#ù$ $ $$$)$)$9$9$I$I$Y$Y$i$i$y$y$‰$‰$™$™$©$©$¹$¹$É$É$Ù$Ù$é$é$ù$ù% % %%%)%)%9%9%I%I%Y%Y%i%i%y%y%‰%‰%™%™%©%©%¹%¹%É%É%Ù%Ù%é%é%ù%ù& & &&&)&)&9&9&I&I&Y&Y&i&i&y&y&‰&‰&™&™&©&©&¹&¹&É&É&Ù&Ù&é&é&ù&ù' ' ''')')'9'9'I'IAÉAÉAéAéB B B)B)BIBIBiBiB‰B‰B©B©B¹B¹BÉBÉBÙBÙBéBéBùBùC C CCC)C)C9C9CICICYCYCiCiCyCyC‰C‰C™C™C©C©C¹C¹CÉCÉCÙCÙCéCéCùCùD D DDD)D)D9D9DIDIDYDYDiDiDyDyD‰D‰D™D™D©D©D¹D¹DÉDÉDÙDÙDéDéDùDùE E EEE)E)E9E9EIEIEYEYEiEiEyEyE‰E‰E™E™E©E©E¹E¹EÉEÉEÙEÙEéEéEùEùF F FFF)F)b™b™b©b©b¹b¹bÉbÉbÙbÙbébébùbùc c ccc)c)c9c9cIcIcYcYcicicycyc‰c‰c™c™c©c©c¹c¹cÉcÉcÙcÙcécécùcùd d ddd)d)d9d9dIdIdYdYdididydyd‰d‰d™d™d©d©d¹d¹dÉdÉdÙdÙdédédùdùe e eee)e)e9e9eIeIeYeYeieieyeye‰e‰e™e™e©e©ÉÉéé‚ ‚ ‚)‚)‚I‚I‚i‚i‚y‚y‚‰‚‰‚™‚™‚©‚©‚¹‚¹‚ɂɂققé‚é‚ù‚ùƒ ƒ ƒƒƒ)ƒ)ƒ9ƒ9ƒIƒIƒYƒYƒiƒiƒyƒyƒ‰ƒ‰ƒ™ƒ™ƒ©ƒ©ƒ¹ƒ¹ƒÉƒÉƒÙƒÙƒéƒéƒùƒù„ „ „„„)„)„9„9„I„I„Y„Y„i„i„y„y„‰„‰„™„™„©„©„¹„¹„ɄɄللé„é„ù„ù… … ………)…)…9…9…I…I…Y…Y…i…i¢i¢i¢y¢y¢‰¢‰¢™¢™¢©¢©¢¹¢¹¢É¢É¢Ù¢Ù¢é¢é¢ù¢ù£ £ £££)£)£9£9£I£I£Y£Y£i£i£y£y£‰£‰£™£™£©£©£¹£¹£É£É£Ù£Ù£é£é£ù£ù¤ ¤ ¤¤¤)¤)¤9¤9¤I¤I¤Y¤Y¤i¤i¤y¤y¤‰¤‰¤™¤™¤©¤©¤¹¤¹¤É¤É¤Ù¤Ù¤é¤é¤ù¤ù¥ ¥ ¥¥¥)¥)¥9¥9ÁéÁé  Â)Â)ÂIÂIÂiÂiÂyÂy‰‰™™©©¹¹ÂÉÂÉÂÙÂÙÂéÂéÂùÂùà à ÃÃÃ)Ã)Ã9Ã9ÃIÃIÃYÃYÃiÃiÃyÃyÉÉÙÙééùùÃÉÃÉÃÙÃÙÃéÃéÃùÃùÄ Ä ÄÄÄ)Ä)Ä9Ä9ÄIÄIÄYÄYÄiÄiÄyÄyĉĉęęĩĩĹĹÄÉÄÉÄÙÄÙÄéÄéÄùÄùÅ Å ÅÅâiâiâyâyâ‰â‰â™â™â©â©â¹â¹âÉâÉâÙâÙâéâéâùâùã ã ããã)ã)ã9ã9ãIãIãYãYãiãiãyãyã‰ã‰ã™ã™ã©ã©ã¹ã¹ãÉãÉãÙãÙãéãéãùãùä ä äää)ä)ä9ä9äIäIäYäYäiäiäyäyä‰ä‰ä™ä™ä©ä©ä¹ä¹äÉäÉäÙäÙäéäéäùäùå å JJZZjjzzŠŠššªªººÊÊÚÚêêúú  **::JJZZjjzzŠŠššªªººÊÊÚÚêêúú  **::JJZZjjzzŠŠššªªººÊÊÚÚêê"j"j"z"z"Š"Š"š"š"ª"ª"º"º"Ê"Ê"Ú"Ú"ê"ê"ú"ú# # ###*#*#:#:#J#J#Z#Z#j#j#z#z#Š#Š#š#š#ª#ª#º#º#Ê#Ê#Ú#Ú#ê#ê#ú#ú$ $ $$$*$*$:$:$J$J$Z$Z$j$j$z$z$Š$Š$š$š$ª$ª$º$º$Ê$Ê$Ú$ÚBŠBŠBšBšBªBªBºBºBÊBÊBÚBÚBêBêBúBúC C CCC*C*C:C:CJCJCZCZCjCjCzCzCŠCŠCšCšCªCªCºCºCÊCÊCÚCÚCêCêCúCúD D DDD*D*D:D:DJDJDZDZDjDjDzDzDŠDŠDšDšDªDªDºDºDÊDÊDÚDÚbªbªbºbºbÊbÊbÚbÚbêbêbúbúc c ccc*c*c:c:cJcJcZcZcjcjczczcŠcŠcšcšcªcªcºcºcÊcÊcÚcÚcêcêcúcúd d ddd*d*d:d:dJdJdZdZdjdjdzdzdŠdŠdšdšdªdªdºdºdÊdʂʂʂڂڂê‚ê‚ú‚úƒ ƒ ƒƒƒ*ƒ*ƒ:ƒ:ƒJƒJƒZƒZƒjƒjƒzƒzƒŠƒŠƒšƒšƒªƒªƒºƒºƒÊƒÊƒÚƒÚƒêƒêƒúƒú„ „ „„„*„*„:„:„J„J„Z„Z„j„j„z„z„Š„Š„š„š„ª„ª„º„º¢ê¢ê¢ú¢ú£ £ £££*£*£:£:£J£J£Z£Z£j£j£z£z£Š£Š£š£š£ª£ª£º£º£Ê£Ê£Ú£Ú£ê£ê£ú£ú¤ ¤ ¤¤¤*¤*¤:¤:¤J¤J¤Z¤Z¤j¤j¤z¤z¤Š¤Š¤š¤š¤ª¤ª¤º¤ºÂúÂúà à ÃÃÃ*Ã*Ã:Ã:ÃJÃJÃZÃZÃjÃjÃzÃzÊÊÚÚêêúúÃÊÃÊÃÚÃÚÃêÃêÃúÃúÄ Ä ÄÄÄ*Ä*Ä:Ä:ÄJÄJÄZÄZÄjÄjÄzÄzĊĊĚĚĪĪĺĺããã*ã*ã:ã:ãJãJãZãZãjãjãzãzãŠãŠãšãšãªãªãºãºãÊãÊãÚãÚãêãêãúãúä ä äää*ä*ä:ä:äJäJäZäZäjäjäzäzäŠäŠäšäšäªä«++;;KK[[kk{{‹‹››««»»ËËÛÛëëûû  ++;;KK[[kk{{‹‹››««#;#;#K#K#[#[#k#k#{#{#‹#‹#›#›#«#«#»#»#Ë#Ë#Û#Û#ë#ë#û#û$ $ $$$+$+$;$;$K$K$[$[$k$k${${$‹$‹$›$›$«$«C[C[CkCkC{C{C‹C‹C›C›C«C«C»C»CËCËCÛCÛCëCëCûCûD D DDD+D+D;D;DKDKD[D[DkDkD{D{D‹D‹D›D›D«D«ckckc{c{c‹c‹c›c›c«c«c»c»cËcËcÛcÛcëcëcûcûd d ddd+d+d;d;dKdKd[d[dkdkd{d{d‹d‹d›d›d«d«ƒ{ƒ{ƒ‹ƒ‹ƒ›ƒ›ƒ«ƒ«ƒ»ƒ»ƒËƒËƒÛƒÛƒëƒëƒûƒû„ „ „„„+„+„;„;„K„K„[„[„k„k„{„{„‹„‹„›„›„«„«£‹£‹£›£›£«£«£»£»£Ë£Ë£Û£Û£ë£ë£û£û¤ ¤ ¤¤¤+¤+¤;¤;¤K¤K¤[¤[¤k¤k¤{¤{¤‹¤‹¤›¤›¤«¤«Ã›Ã›Ã«Ã«Ã»Ã»ÃËÃËÃÛÃÛÃëÃëÃûÃûÄ Ä ÄÄÄ+Ä+Ä;Ä;ÄKÄKÄ[Ä[ÄkÄkÄ{Ä{ċċěěīīã«ã«ã»ã»ãËãËãÛãÛãëãëãûãûä ä äää+ä+ä;ä;äKäKä[ä[äkäkä{ä{ä‹ä‹ä›ä›ä«ä¬¼¼ÌÌÜÜììüü  ,,<<LL\\ll||ŒŒœœ¬¬#Ì#Ì#Ü#Ü#ì#ì#ü#ü$ $ $$$,$,$<$<$L$L$\$\$l$l$|$|$Œ$Œ$œ$œ$¬$¬CÜCÜCìCìCüCüD D DDD,D,DmAójPЊ†ƒBÄ ëð_€AÒ&à‘7ö´'µ Âì`7‘¼ˆ˜0|Á„R¤"•!/Ï ~xR– TZ Aüàë¥](A²Â –  ‘ôÀ'¦XV °)ÒAN’ *aPƒw€¼ùÈ0E (Xö°—µ…*D)R!e· -¸`7CºD¢ =n‹pà´ª¥P4 ²€u”œ Ìá! hO,Âyf «ùÌ`.cŽ> qðj_CRú?Ïñþ_h‚ûD2ç!—9}›è oàSD€Ýcë>"Añ<€‰ä»¸%ÝÁJ P YN‚ÊtÀ<†n|3sá¶Å ¶(tnC£r;“‘ÜœQzˆÃïSz™‹ˆ\BUBª„ˆ $[<"Ùà-Áh¾ øPgƒªHRAê/PHDB Ã`ž] *èari “HccËPÔZ‡Ð8~ßøÐ~ô€!Va ³ ýÈgîCZÓøÝV†ê´9qÈ3Ž®4uq£Æš4Ðø]GÂê?ɱþM^ ‚õ2ƒ!”jH›R hS@ƒ81ÀÜ´å >ð1‰Œ„¸ü%ÇáIe K(Y"ÂÉü ¿åkÀ3^¶ °°tO¢xÄö$ˆ¼@íâ"•¨nÄ{v%Œ,d ϸN}Âx ªŽ…Tt,Tqb£‹´\ ¢ûzÛÐÅ›†,Ü3±˜½2„i”#g®=pਇD9ÚñÎ׎ãTw£Ó°€û¯GÝz@ž2ñ“À„ž?ý!ÿè&"1 ;YØ;XÚÀêP¨AN v0„î€'tVÆ ¶0\{ãØÑ Ɖ |5áÃE(wšÃ¼Ö™üȈRÜB–â/Ä~ ’º„•Ô&_q2ûŠtP#¢œCâ­Ôn -'ai; ¶p]³ƒD€ÈçFG:3ì1Ÿag@k:tݦèãôG¢:­áÕoxÀƒáˆÿGø Aq" ‰Èà†GЬU`)zÁKÖ `ˆƒp܆à÷]ºèD§%8Ü –á"Ø)ÁcÜ à_ÆÂþ6¤Í †Õœ6¬áÐ[‚ØzàC× l`†ÐD6‚<ÚæÐ–°'0Ñ9†Š90QÉ‚©@J±…ˆÌ-÷1o¹‹êd_S#¿­øÌ3a˜4¿!¥ù ›ülßãó˜ç@:;‚aÜLÌzfcî'q9MhBD ýœ‡ìà—Û¾Ø,ÌÁff åg,ƒ¥˜,ÁŒ$`Gì‚?d­€lX\*Âáq= ‰èc CbupÓ«‡ X8RÁÝŠìP~,ñ`!=a ë»ðEß‚J PH™E„Ê,(Á@ m$Si"¶o³x´eE£*.Ê!vQ  `ù"îpÏ~Æ{ö5Žñ¬wÐTn‚£"yê‹ÇT^°9õêÒVq„ Œ"Q‚ˆïäG"W¸øœ‘DäŠ(Ö±FµŠ¡àUÞð·ªÅ½V/|èŒSb˜£/ëXÒ¾•ð6`Q³Ž¬p%cœQâˆíׇn¼=(AéBµà}¯… D)êÈGVÁð>‚\°倲„” 3j›T‹pt[„t {¡øNŠBtRS`ª›Áp. ‹‚ \iªMPÀàÎs;˜A÷Ͼx„½D%ê"á± ‰$ƒ=èÖ Æ°N73A¹š9hqËC©NJpñ#G‰=øïÀê8QÄ´ ­¡ 6ˆa´.)t¸  ʼnNJp)Hè û0_Ùƒkd[ õÿ¯øD<Â!æà –`(ëbL `_\‚ú䉀ÌLÎø6wÁÎËvXz|CÓâ NQrˆ€,Db;1Ùˆ•‰D¬J'!8™ 1`Q‹§~;ð°©…H-ÛnØ‹ã\_ãäŸ ˶]°4Ÿá¤ÿ ”l¤ƒ€1ˆæÕÇ6®;fAÛ2F(z1Cì°eõˆ¬B.2qÈž@`JPÜöà gÐK>‚ÆŒ4`ÌÉfH9ûÁÏÞ/À~xˆ#ÄA9H Ê@U‚¨Üö ·±*„1T!¥• ,¨p.Ãv¾íð‡ÛT>Ú¢ûØ‹HDZB$‚á$ PLj‚~aó¦UE2ª+G±Z=‹> Yñê®UpÁnÆ v2pŒðg€ãW¸ Üކät8Öư¡´u £Ã“˜÷¡Ç½?šÑüÖS°‚„/à! Ån(# )µä ¯ ˆŸDø(ñAGŠ î°_uƒgà?õ¨ðD‚ $³€•œx(ËÁak X_$Bù"{pËۆʬ6UaÍÑnˆz=ÃÑî >±õˆ{àCß:Ðð•Qªˆ'8 -xQk¦k3X°dEƒ"-ÉánO ÞH^òC¸•ÀËqF[Š4ޱ¤uDl‚#øðæ‘4ˆ;V¡ÚµB@zë\é°È †B’ô€7x»À)6I°Àˆ†ö/´ê<Qà•µ­¨,0a„ ¾€eôœ8áÁ4 GJ:P†pœ3…Ml*kan tbiÃNI°ÒM†ÿ7ø!Úç×8}}ëè!t°8EÂG8˜DÄ‚'ÓQ>šŠaSB³h›@³Eœê.™±tÍŒ `•œüàΰ†u„5\ñªçÃÔn£Œ`ØéÐGN‚<$áá'uÐ{®ƒøšÄÑð'€Bîbs Øh ™@lÊ(¬±ü à‡¾=ð(¹EÈ Ý€^ìcøÀô$¡ CÌBb¥p•+…,(©a`q ˆ^åÂ÷.h°ËE†ÆÄ66!Ì¥e(yùÏÈ -lwøC¿Â8òÇ•¨0&òQ7’Š(dQC"¥X*À°€˜-µ‘m¬‹Ùü^Ï㌌`Ë,†Yd4za£Ó ‹”l\£}ÙîÈæ?Ç1þ;BQÚ=,yécêŠTQl `B bkÓl†›` /ix @Pª7°!½z Ñy®Íp%5)¨ ÿ Wý+¸]Àæ-1h@HBBÄpŽ#„Ý´&í¡Ra “[aÂÛ‡°Ä=†Ž„4t!¾® õpvhƒ³DL€úd>ðA÷‚*âW‘u„‹¬&Á0~ ðˆO„B—/¹x¬dx,Óf˜  ô]£cÇ¢F=3™aœË R(j‘CoÉ~Hâ»ÇÞ:aQÓ ìx'cÜaãýáÇïA*Ò V·L…ºd;M!Úi ¬ˆMdCDR"€iH 5„¬  ð¹à5ÏØ€¡êP/7y¼ ÐlƒÌDb!7q¸JJÂRVE¢(…}Ü+îázk ÓXe^*ð àØO.H9rAæ¸5À€kX!Í!ißFøÂRì—`›xÛÀ(aDƒ LT‚b¿ ù¶…´(/RzŒAbã+TZ Ñž†Œô6á°· ñìoc—¡½ì¾Geò<áñç¥}(¤k #YäH?"BÒB’ê܇Vä3–!œ±D‚ w@º hS@]Žìp-ñh = Ií»œÜàÊ Ph9@AÊp€„ll#ca6A ²TMB¢j۶-†<0éá¢\ ào`ƒ{‡`ì;Îp>s‚t€Šm„Sl$J¡"U ~ÜKöâzÄÖ ¥tE+¢+ QXb‹/HYzBæø7ÀÀF 1Ò±Ž•ŒààgS,™`ÛšÆÜÖ8•ñĝޒt£¿«ýXö´Gµ¢?b‘ûE<‚)ä,u!c©‚tDx"#ÁËœ†\ä@z"Ð "€i÷à'¿ª T€…±-ˆ(5ÁA® ¿Ð]þƒ[ÄÞ ò¸CBƒ”… ”(d¡^K òX^OÂò~DÀÊ&½5èÊfS0yVƒÊ´ @mÐCn‚6h³@”c„£&È!6A  Põ¢µ¨¯p…{„-‹al[ Ï ^xcéwHÊ}†Sì4N¡¢u Ükþã{Øè劇,T;ب2‘ðƒL„d"…, 0Hi‚^@òžY„òÌ)G1J9нœUìâÊtS ¹`EË0 q€SŒnÐcvƒ6¨µ@ÔmF£j6ͱ¶mŽ q#£pï|h=•¡ì­Ò~Ø ~Á ¿ˆUüDbB#NÜŠväL–"d±ŠH´R5à¯:t Ó i‘Lˆ!-Á n ú°OÕ‚ëDZ ÕÅ®(<:ÁáÖ½ð…ï„›L$ÚaAù ÈWA‚º ~»ð†K¸2]Á® p rB’?Àñþüˆ?äBаB„j%( ¬Md‚†11ˆ¨IEBJ+Ã!^ ]`Zëòe“(Ã\†ä2†a”3 Ìhnc^™ôÈÞi†óL9I¡ÊM¿uøÊÿWøù‰GÌJ@B²qăŽ$7°!½Â¦F ²0M‘e ‹)fÛ#6ØÀ€¶¸-ÀÙÔΠ‘›ŒØ+#ÁY {PcÚƒŠ¤U ýìèF0Â1†;p™Û…:¬)ÕaiÑ Nˆa7ƒ ¼ûÏ܆ë7XÁÕº­Ð|8áÀ ½Aê› DÙAîp—8„¹Ä'~ñ;÷ŠKŒR\b­ðo€²?E‘ú.?qø‹ûø_ßÃ$Ñ ÍLFjb5ᨠ¬ÈmfC†?1øèYGBÊ;ȱÞE^Äzö#ò×–¹‹È^B•Rª‘ìˆd_¡"ý SHÚšG:b9Ó5Ä ® heC( âÁ çðO?‚åÌ.`Ô™¤È;ãAߨ…@„•Ô$®¡@› ØVã·h0»A†EÜ2.ᬠdèqäC"(PñB‡õä?¯"†Ä0ŒëgX$ê'P ¦´M5¢„ˆ$@§ë…?\+«±]]‹V¼Zµâð¼…àÂòF’2kÑ“^(h9C\ðç€ÝÿFïú90¡É…¸ÀuÆÉ$I ù‡È”?ú!ÿÑk ƒY6!°9Qˆ¢ŒFÈR6B=ôyï£Ýè€ËÀ~^¥P-*Õ$© =è*ØÁVÆ epc+ƒ…,)`ü?áøEÙB.Ê%™,…54)©¡hA B`ÙÃÎå°Ï-†å<7)áÔC¢{ÍÃÞn ¥Ñ.ˆ•DDª"@E(–ÎD¶r'eñ;/ŠDèR'B¬Gb8±Õލ.&q0‹õT_ª£bÃÌâg4éQ§JoØk~Ãi‰LHÝÀÆî8IaÂKH¤rE#Ÿ¼ýàëSÇZž;¬‘Ýd!py ƒÕ½­èøà‡Ç?QøŠú Õ ; aÙ äÈO&D-"!iA”Š ¤]ø"ïÁâÈ×G‘â<ŒÜcÔö Ë†Xœ3žœðhèCTÕ¦¨Ø“ÆÄž6þ!·ñ õÔo®£‹X@æ ‡1:aQÓ ŽÍØvnÃÁ Hó§8=Áaî §l};c÷n»q@H A*Ò V·L…ºd;f!Û1>H‘òEkâ+_‘DŒŠ$qä#!ÝÈþîHÒ2F‘0L ‚`g99È ‹AZ ÒN‚àT Ó;™Ø;‹ÁÜ^’0„‘„\$‚á? øXV³þRPº’†@d2!« Xhq€CŒPðz‡ï¤?}"¸xŒ€Äd$Ïq&{‰ M‚‚ßø§E< +‘!\‰ O´Z}¢á€ »ÄÅÞ&/ÈÑ~FŒ(€aD¼É>ÆIö3(á™G „h#M›lØÖˆ¶\6Œ´`ØìnÇcƒÎpäKÇ"^9ì!Ïa°ðu‡ƒ¹ÏÎxñ؇ŽÄ=OQêzŠ |Qð€Øÿk‡û\@´ cPƒ„&™!4É hXDò ß‘=H‰êD\þ"çñ¤HÕ"G…b<+¤½$“|$›àžï„÷|(•D¨Š[,RÙb¤^"ð¬oÅc~+ó‘_œ‹30Y™‚Ú_Òø¹öEϲ/S¡z 4`Y£G‚8Çv†;´2¶Ñ•¶ŒãœgãFz3ÐÔöƧ¶6á°· » mÝ|{ãØâ}Gê9xËÄ”lt£c²®•pð €P<Û±æÝm8{iÃè¯Exýìè@@rFh‚3D- ùi 6HY²C¦Â6 ĉ$UÄ"®!ÕÈÆ®G¢8uúXÒÄŒ)$aI&{‰3Üp,{Ϭ}`Žßvø*AT Ob|ƒ´ý úá×EuB+ª ˜d….ô)w¡f± 5ˆ`uḭ̂Îe†Þü6÷áÒ³•˜{iÃÛN ‰±MˆŽƒô–jD³R&p¡3… ÒtN“¢‚¸£ê…T)бN…ŠªUP¢¸ÀÀ±jÅ‹V-2Qi’‹‚\ÂîpȾäÅ÷&0’a„“ Zäb×#$3!˜Ìec(3òqŸ“2„i”#Z4Ñ ÙñÆÏŽ7U¡º­ PpZƒgƒ8çr;:·AÕºãTw£Æh3@ôþǧö>Q𺼠}áü›äÙ‘ÈŽA}¢ í–|„³ä32!™‘1HŠDå‚',p‹€„i°#M×î¸HNòBw’J’PD %©+v‰[´%&ñ)7‰¤Ký"m|kàž½„õì(…qD+ŠWDRº"£d ¬=Åaî+ç_8‹/HYzBÙeË(¹·Å;/G!z9 °`=ƒ{øÇ89À2§1•9Œß´fý£E€,ÔÄÆ¦&6ѰF¸€mÄ{ÜâE(9háËG„t„#±´ ïÑÇ~Ž<Ìæ`iP{Jƒçç?8ýXGêÂ@0Ò†B€‚3 ñ™ ñˆWŒC˜²Å‘xˆãÄTÊ"¦Q—HĺFÿ7øö °d‹H$ZA&= 1èJhrSC’Ðh–ƒ@JµU¨j@ËR ð@g‚o x`¶·µ¸4jÁ£VÉðvO„L òa"‡ 8O^Âzö†ð¬7…Íð.oŽp s€jYRÈE€â,}0;éú@Ò…M*h#öìG·bKNZp–+ı^&b‘3‰ÎŒNtb6 °£¬`)Ä1N!ЦU4‚·¸ð±,E‰b-$Ai" ~ø[÷Âíhø¾¦Eõ20‚Á„ Vüb·ã#9ÈÌ3a˜3äaŸ# /di{#Y:ÉÐÙ­Íh7Dqº#Žhp;Cm{hç9Ç9Î:§¡Õ=ßlvûcÅn+pôÀG¦>±ð=¸8}ÁÃû¡Ý MhAo’ |’0„‘„28!‘ÁòÈ–DÕâ&¯kÄ‹^$h¶#E±’Hì’H?RAú’F ’1Ÿ$øÙ+8 YÀK§2]9ˆmÐCn‚)H8¦„m4$?±!ý‰F8J1Â^ï÷x› „Ù'ŸÁ<þ að¾tEó¢0s!ƒ™ R°b•ƒ"?øËô†_¤3ÔÁž¦ +|i[ãX@ÂÙn†Ët74ѹ¦Ž€pŽss˜æûG7Ú:˜ÔÀÛ„vÜ#Ä$hô{‡£Ü=øïÀ´P}¢ƒúŽÔqHBA[B Ú€„l1%!‰)®}pDIJ&%‘gx‹;ÄgŠ#H­J…jT,+Ña^‹@ÜZâÝÊîPºÑÖˆ/q|kŒà`DzÈQFBŠ2ëñ—_ŒñHgŠCIÌN`Õׯ®¾6L²` ÉLnJcÍþhãXÀ9¯1ÍyŽ¡´u £¶°ðØG†Â=Aèzy¸{ÍÃì`þeó(@rr“Rè‚—D"M!i ø_ÀCÚRÒ‘,à‰gXä"Ç!ÈÌîG@¢:<9ä{${Ù'=I9êJªUP’ᘗ ÄÆ&0‘4ã §N‚pœ·$5¹!»\ Úàr/C‘zeë(ŽÄÌIöb]è š£„Õ'€< lP³b“˜¨¨…@ì*ßVø î WpbÉH°µ¤­ .?qø‹Å¬^-bþþ÷ðÃ$F"1 ±Œ°díƒ4ÿ§øÐžF„ò5Á¨ v|k³ãkXÈÞ†ðô8`ÑÃŽNrpã¡Ðë¥](;ÂqÞ&èy7C×Mºhù1ÇÉŽ?%¡ù-ÿ´ý¤ N jq¸H5ÂB‡B:Øä†Ç$CÌ"aWÈ¢¾Eð²/…‘³@šzc#Ó!ý‰ìIZ"JÑœ”lä°ú%‡Ñ/£I}LÃ’f“gø›?Äç‘'<‰=I êH_*øÃ€‹Ø^À)³M˜ `àrЖ€÷¨½@D§%8×p–»…!¬) ac_ ø_”Âü¦”pÌ£†š 4Õ´; ¡Øpgƒ8ïÐç~‡r@;’éñOˆ}áï NQrˆIàBOÙþÈ‹[ZØ#¬Ñf‰!€I UÁ®˜Õƨ'q8s‰ù„OÌ"‹Â^¦O2x*lñSgŠÑ$V‰"Áª P³ÉžH-Ëqn[‹©(]IB÷ľ ÁIF J1+‰\ €ÈdC-Ån(ÎÏÆv~4!¤i XÌjÆcc­hÜPâ€7í1¿iŽ1˜qŒÃ™àÏéÜÇNæ;MAÚj œxLãÏá÷]ºè>°qõƒâ$ 0¡éÈ'NB¢»4…Ù¤<`!ã‰H”JE{‚+Ü•Œ¬„r÷#—¹ "‰HäòG'’oì“d©Ž%Lq-ÈInBLNbbsJHšRDà%');tIÛ¢O¹b}Ë:¬)Õa\ à`ZgÂÓ>p»€L0’a‘ô  gáÃ?΀Ötéì7OaÇÜ>àuOCªz-ñhÀÄ>!ýÄî ‚ÉDJ!‹ \˜dDÃ"3¬`CD‚$ê'P pK€"i{KØÃ„î(HBD HlRCbŸ•ü¨«=…Yì+§]8 YbÕd« ¸·…ż/x8‹÷¬_½c ~[ðÆ>1ð2h±“EŒÏ°f}ƒAf 0Ó¾Fò5ÈÁ®F ¨m@Ãw™¼Èá>‡ ô9'AÉ:€tã­šlÐîËGvZ<ŠqäSXèzÇCã›ØüK‡â\?êÿT0ì‡dÎ Îq ØHNÂCOBz äˆW$PL"‚a~»ðF¸²5Å‘å@*†ã$7%#É)J""Q¿œ•üä½z%ëÑ2ɉ–LM‹’l\“™øœÏÄô*'¡Q@oJzPø"‡ÁŠˆ T@}–ì°&"1 6PY²ƒ9dË éMJhAÂð0„²X%’Á9÷ ϸQâ‚N°ªu…‰0,Ioß ~ø_Pú€­0Åi†`Ð3¥Ç .8lÊfP °à]‡8p9ÃÛ}Ûèz=ÃÑîh ûE¬@}b~‹ð‡·Ä=¾"Ç!9çLG:bGf;0•1Ä©Ž&%¡1- ¿PMú‚}5騢«Å^)„!L! –ðT·‚³Ošx°,`,â¡g nô[w¢é7I¸½¦í00A!‚ F”b4£8ùÀË,†Yd3¡1 ˜hôÃU ©Ø¬ÆÅf7a¸# ÷o¸‹SZ˜æ-1h:báÓÏvx#Á; Øó³‡œ=Æî0§Ð}>ƒ÷n»q@H A)B J*!P!â¿IPÂJ†-`™kÜ(áMÊ nPVʶVˆÀ´FØ|.ÃჀ dDÃ"&ç@Ï:¯¸5}Á¹ Ìq¸ƒÄD0ê!‡‡X<:Áï7y¸2ƒù” ¢±ˆ^øB÷Â%(øŒ¬„ed$1 ‰6˜I´Â[Ø8š DÑ'_±:ýŠ8Pq‘ˆ@§šE<Ò*¾1UñŠåØW.ÂÆð7€µE¨¢.Apò ½x]ëÂüñçˆÂšÆÖ1|Á‹æ •|d«ã2Ù–ÈЀØ4Þa¦ó mäko#hÚFÐÝ•ì¨8>qÁóŽEèr/CŸ øhÀ¨Žó°7‚(¼Eà¤ñ'ˆ/ùAÊ ­mlƒ è@õÍ®h@Ë‚\ ˆ`„xˆ#ÄA+ƒ \NE‚r,gp£;…P(*AaR [¹BÝÊÄ`¾#'d1;!—: ¹Ði3CIš"àÙþ<7ñáÍ"iv Ãµ`ô ÕÜ>®â P„Ä Ö!ßáÿ­|Ekâ8ÀÆ‘”ÄŒ¦%;A)Ú …L(ânÁvŸ„øD(™ÁDÎ \¼Råâ¤$€¬dx+ùÑ_΋4\Y¢âÚªÕPº ÐH/XQzÂŒ ``c’„ljF¢ÞðƒÜDâ!Í!i¨ÌEFb7ƾ0‘IÄŠN%+¡)] €ÐL‚m•l¨žÃÄö(Š!DQ XpR£}è¬=Åaî+è¡_E 0Y€‚ÙeË(¹¾Íð/G!z9 `@£{ø1JÁŠV +ài_€|àí€l>ÄÁö&‡@„:WT"º¡#h @L2Ba’â Ÿ.ô)w¡Y ÈðY¬BÍb?¹ü†001Ží whg 9žÔð†Ý6èAÄÕ&¨tƒ¤lüï䇴¨=¥Aú‹ÔX‚„×t&»¡Cp €T4B¡¢ä°¯%…®°-uy? Éøa¨ @@ʆ†P42®õ w¨oƒx¬žäô‡](:éAä«%X|ƒä|ùðÿψ4ÈA¦B“Ô˜‰ýOè#XqÉ H`"Pbƒ—}D»ê&¶ñ5·‰ã@O†J2P¤÷E'º*qP«ŠºàU×¼2á7„¼$·0u¹ƒä Ág38Dò' ¡ºŒ%Ôa<6 á°Re“.o€«|’,,‘aqì `_ÓBþšÊàÆWi3H!§¢ =mMCjj)`áK?Ü9þáÝŠìPz´ƒÕ¤†Pü2ˆ@¸ÂYšÈˆ.„At"á± ˆî¸GuÂIHx•¨„­D&@12‰ÆXN2Âø€£Eâ)ž±LõŠ”Tì ñšŒÐ?ËAþZÈà†Gg¼#=á'‚ <M8ÂiÆ$@¡">”)ô¡]8 éÀZ¦BÕ2 »ý40±¡’Õ –¨h@ÐÜÖä†íp7kȽEèu‡ƒ¬<;ñ؇ÄH>"Aþs󘃄 !–q ³ˆ› DÙ4[¢Øoƒx$ôñ'§‰rÀK–j*QPéïH(PQB‚ŠIüROá;)ØD§%8ð„¶@%²:ñ ׈R!‘\Àªæ|,kápÀ †_ˆBüB»@ÅÚdT3"¡¦v 3°mCh àµ;,9ÙaÜ^âðzoÃÓ~rûÌ@–b-‘h‡ã„?"ÎñwˆêGPBGã?•]„ªì&+á1_ ÀàN}ËîX¢ÑEŠ·°…½„c #a&V 2°LíÂgn€ Œ:¬)Õa\ à`Z[BÒÚlà»g„0Œ!‘ ŽgÈÃ>FË`Ö[çø7?ÁÇ‘<ˆu<ƒ©ä%0ñ)‡¿˜=üÁýGê8‚¶„´!ƒ± ˆ–pD³‚3/™x$ $ß&ø‰nKp‚hþGð—Äì¾(=‘Aì„| #àa,d c NqBsŠu€£¬Rä*—!b Ð[åß(ÏP¾z†* 1Q—é ¿HiRƒJ”*°ÙU‡ø8ÁÍŸløvÀ¶‰0ôI‡×Ð>¾‚U¨„:!Ð!æ!1¯ Exb9$É ‘­Än%A* †¬L5bnów˜IDBJ"(°™E„ÿ°'ýMM jhV¸µÀ„´ …Öˆ.´Aƒ5 ¨d%ƒ!,ßpÎû†­`5k¸ë ÇXqŒÃŒf<`éㄜ<$áîˆt@Ãø6 —Á¾[tBÛ¢$p#€ŒtDc¢#öA² 3I˜¢Z&Ñ0™îDÏr³€•œâd'!Eú /ÐTãB§à°w¹<-Éá{É ÞHbJƒTkÐË^†x4ƒÁ± ‹øo¸}ÀÇ0æ9‡gP;:ç59¨}2é "‘ˆ>(AñBè芙DTÊ#ü dH«"Rì—`˜DÀšìŸ`0„)„!Y‚ ÌYÅBÎ*G`º;\0:á8 yÀg2Ã9–¢ÀÕÞ46ñ¡Å )tš¤Ðÿ°ïý‡µp=«ú½Õè‚ ![ ؈ŒHDbB0¥…(„| $¶q%³‰cèKADÎ &pT‹Â¤^ü ¯á´Œ-¤azk ÓXaÿƒüUðʯ†‹4X°S ‚˜om{h±P劇aØ;Áæ 0H|ÚƒæÔ ±eˆ9xA˦Ý0ŠNDRr#i¡M ìHbQŽŒpR½B•ê…`¬+–Ü,¶ás ˜À`*ÃVàÀÇm´3m¡¨Î Fpm˜ClÂ:áÔ‡Dð:'Þôèzÿƒ×ü•ðü¯ˆÈ@ÞBS¢˜ˆmCh"ôq£ˆò G•J PHT@¢æ@¯2¯-x¡y? Éøa¨ @@ʆ†P42®õ w¨oƒx¬›päÛ‡](:éAä«%X|ƒäø`ÿÃ3œAœâzÓЉöÄO¶#SÁž GÁÿŸüøƒ@z ÓÑÔ 6 aÂ}ès÷ƒŸ¼Óðª€=Tø3Á˜e (¯€Ý|!d9 !Õº­ÐxÓCÆš PøJ‡÷Ø?¾ÁÀíhs“ƒœœºðíׇ¤@="öŠ´P€úÄÖAꇆ<4ïx(ƒøÌ `íœ<ìáôȦ@wþÿöÕÀö®Ì|>câï“è¨û@/ÚWÀ ¾¾<ñà-hð ·ÀU¾P°"… P @)H%¹(¦à-7`X ÀU¥­(Ó@¦šF€:4È@Bo¸}Àd€Û$³ 5£$  ‹ñ_ˆ"rÁ–xÀCÆÐ¦€ƒp -låà?/ްu€¡m h'Ë>\ ЀN„jÀV˜qÈ%’Á,– ?0Iù‚FÐ6€P€ b€› `\{Û¤Ý ´ª¥P,¡e àX/¸ÀÀ«à_*bS tS¤‚”Œ¤`nZrÐú@×Ò”`4£šð ׀б…ˆ3œœä ÆPf2ƒ(˜DÀÈ@1|Á‹æ 9°a̓81À¿Oúx/=Áyî ­]h‚áä ŒUb¨"Aúw0C¹‚¤ ‚F0ïÿxÓ >™˜´Å ãîp8~Ãô ý@oêvT² ÛˆÜ@6RA²’ sÀkžSôŸ Ò¾•ð4&¡0 äg 0€ ÉÛNØ+Ì^d Ê€VT©@J§Æ>0)UAJª ,°Qe‚ ·í¸&Ñ6Œ ŽàLwYÌ€ý¶í°>ä÷ ™À|ÎÝØîÀõi«H<ÊæT`x›»ÜÞàìêgP:ªÁÕV†Àt6™|Ëàä 88rà ú oÑu(©@Û$Ù 63±˜ e°k-ƒP €`ÑÄŽ 3ÛžØ Î fq)`KÇÎ>p1]Šì 0Pa‚ƒP€¾ ðP.æAw2 ”\ ‚Û@Ú´_¢ø,uAcª ö@W²Tü"§áKšXDIB"J󇘄4,!¡a X¸B6°n@ƒr” ”¡˜À@B²ã0ƒð˜„ÀùçÏ8=ðAï‚X zĄ́e@ñˆ ;±AÝŠÅ@v*¨TB ç½=è9Sʘ-°qmƒ¨ @Þð6î·t “l˜Zü×àÔg£84ƒÁ¤ øPgƒ4´¥ Ê¼Uà2AúΖp„ªì%Wa(à GI®‚MtL`’cŠ€$T ¬ `G¡‚= É ŽIi°#M_ÂøEˆ,@BÀŠH"@Á®}pChBB¶ …±$Œ!$aý7èA)B J$Ð&„œ àý¶í°>×ö¼‘ð|ƒÚ¸ÕÀô=¡èu ó¨OÂxž§@:á8' Á6s ³˜MBhš%™,„ÀÌ&a.& q0KXŸ0”ù„Ÿ4$ù¡%À .HàBG ¡|Ô#æ¡ÝæèF§‚5<‡€Œ<X€"ÄÈž@Dh‚#Dô ‡¥3!˜ hS@B‚„]‚è„ ä o!: Ð?¸ýÄÈ ~EèÈF@÷ó¿˜Vy‚³Ì «ùW”*¼¡T  PTB£ú ¨8T)¡L! aR…”(‚¤è(¿AD 0PxƒÀý0Ÿé„ö´'µ¡;  ÝNXBrÂs°›„Ô¸&¥Á2ï —xL2Ba’è —E°È%†A* P`IíOhUÀ’®Œt$c¡ Þ ðG›B<ÚÄpŽ#„g¼#=á—¼¸EOÂ*~1‰Œ„C"!qV а[ÞÂÞöڶЮL-rai¸ MÀYêÂÏV]²è ,xaaè @Wö¿¶Þp®ó…oh+{AYæ Ï0Uð¯€\ÀªæN4*q¡Q™ ŒÈSÖ‚ž´Ö`¦³,œ)dáI HQ¶Â¶IÀ¢N Ø(NÁ@ ðOwÂ{¾ºÐå„',!7 ¸HM8ÂiÆ(°™E„Á0& .& q0Jó‚Wœ˜ð”Ç„¤$í!Šº UÐb7þn°Ãu†¤0¥!ƒ à`PC‚÷ð¿¿…õÈ/®A{— ܸ^b‚ózð»×…Öˆ.´As® p\tÂã¦úзօ¶ä-·!k“ \˜ZgÂÓ>w³¼…–,°¡c_ øXNBÂròÀ¯–s´+¡ZÇ Ö8V"±d«$…PŒ*„aQË ŽXSãŸ×𦿅,œ)dáI HQ¶Â¶H0¢A… Ø(NÁ@7 ¸h„CD"ðÐ'†z43Ñ¡œ™ äÈfµÃ5®Ž0Ìq†[¼2Ýá•- ©hdÎC&ràȯ=¨1íAv k°bæÃ6˜àÄÇÌ0öa…¦ -0`ìƒdPÀÒ…þÄ/ö!}‹ ìX^åÂ÷.•€¼¬Ý.ìu% ©(\Ææ0 ¸yºÌ-Öal dhZ“‚Ôœ€ð´…˜,ÀAcà Xm‚Ãlõ௯tà+§[+ ÙXV;±Ømð«o†æh73A·¦ ½0mCkú@Ú†É6Há°… „(k¤C]"Ë`Ö[«Ð5^© HiσN|T Ò¥X4jÁ¡{ ØgáÃ?ÚÀÎÖn|3sᙫ ÍXeíÃ/nYÊȆNØ2vÁ‘ Œ€cç8×`Æ»-@1j‰C JaÇC:Qˆ à0W€« X_¡Bý Ä`¾#èä/G!wú ¿Ð]‚ì ‡ì8a¾à ÷oACz ² Ý•äØ7&Á·t » m`k8ÀÙÆÆÄ66!¯¤ } krC[’º0Õц§ 59§¢ =iqÃKŽ:ÑІ†P42Ÿn ûpgXC:³°Í†d¸3%Á–ï ·xe2C)’+ÀÉ^BX2ÁŽ¢ ucÃÆ¦ðÅ7†!$1 !†U 2¨z|CÓâ„€ô$š<ÐÁäÄ& xÀƒÆð¬‡~\;òáݼíàvþƒ·ô£€íat; ¡Ö›´Øu6C©².Pér‡DŒ:$aÏHz@sUš¨¹ åÉ&90¡ÇÃ>qsËž< ááœ8<á¿Ú þÐoyƒ{̽Ýì†ç”7<¡·¿ ½ømrÃk–8ÀÙÆÆ`63¯Y zÈkLÃZf³ðÕŸ†¤d5#!§% 9(i?ÃIþ0°Ñ…†ƒø4ÁŸ øPjYRÈø`ÿÃ÷Ø?¾Áü4á ~œƒôä‹üXÜ>àáõEª(|àÃç øíÀ`>î$q {ƒØÄ«õ\‡£=¡ç8yPCÊ‚4Ðñ¦‡†,<1aß°ý€wo»x¾íð‡gP;:ØÀu‡ƒ¬<?€éüHt:C¡Ð€€s‡œ8¿`åû(9@AÇÜ>àqsËž:áÔ‡Ô86¡¿¨ ý@om{h¸àÝÇæÌ76a· ¼hmlƒkdK€Ú\8@Á0…M*h!8± ňGˆB¸AóçŸ8||Ããæ€ø ¸=ÄìIbHzÔx„€ô$™´<Í¡äG"8x”ÃĦ`ð#yH;ÊAÜà˜v‡Ã´> ì Xx:ÃÁÔ ˆtƒ¤lè‡9œ9ÌáÍTj sƒ˜´Š€ìT_:øâ*âWŠT„R¤"z‘Ôˆ—œD¼â$>!ðˆ¥DE*"Áv|¨CåBhë@†ö7°!¡a `ìCby³È…4) !/Q zˆDÌB&bŠ|PƒkÄ^ »±݈'äA?"@(Š„ T F4 l@Kb™È£ýËþX‡êô?W¡ø—ĸ}¯íxI`úKʈ>TAð|ƒà{¨CÝBÉ@öJ«H=ZAèÅF(yºƒÍÔPðò‡‡T<‚¡ãØ|àøö÷´‰@H?ø\zà#¼qãˆèG@¢8\Âà³m˜#R1‘ˆÍ„Fl"1ŸŒøŒÄ`"äÑ&ˆ²,E‘b*ÉVHŠHR@"tQ¢ˆ– D°b#ÚЈy„CÌ"±ˆyˆCÌBnãp†¤Ä5&!‹ \[BØ‚é§H„½D%ê!€ˆ<4Aᢠh‚ÉDJ ñˆ,@áb(¸€Ïx ¤ý´?í¡ý«íX~íÃ÷n®ðýwˆô@ç¢*1P•ùįÎ%eq++‰SJ˜âS7™¸”c„£$þQ'ò‰8ðIÇ‚L¬e`’ÀÄ–$•¡$­ `HóEï/x‘Ĉ¾$)Ñ!N‰lHb?øÈ\zà#¼qãˆçLG:b8*ÁPšlÐ#GA:Ë,FYb0ð‡€‹¿]ø"Òˆ¬´Ee¢)kKX‰ÝÄNî"V¡µŽAð¡¥E *(PQB‚Š Phbš Р…'ä?$ òOÂzÄÖ žMòh'u‘;¬‰Ö\N²âsîŸpœ‹äX'8 ¹ØMÎÂl´e š°Õ€&á4 ›ÄLÞ"e(°˜ÎÄÆv&á0— ~xKóÂ]Üîà—„¸4%¥-, c KW¸ø›&ÄÙ6&»¡5Ý ÃV¢¯Nzp«o…[|*ÂáV ªÜUVâ©'I8©åÅO.*c‘SŠ’¤T•"£ȨbEC)þOð y@SÊœÀæ¦Ì6`)˜qLÊ_Rø¢–°à¥#)).1IqŠDèR'B_zø£sÅž(ÀÑFŠ(ÈQFBˆpC€¡±Å Ž(PQB‚Š DPb"O x Eª'õ±?­‰úLOÒb}€ìŸ'Äù>'»á=ß ëOX‚yÊÎPž:DñÒ'~ñ;÷‰Ü8NáÂvF²0YDêÊ'HA:B ËlN[bqKŠXœ„àÔ&ú!7Ñ »MØ"np›LDÚb)H =QèÂŽLr`£a(È¡FE .@QrŠÈV@¢s…œ(ADj 0Q‚†ù7ȡŠþ(SqB›ŠôP‡¢ƒ*P žÅö(¡@Í äP"€ PŸ˜DüÂ'Ø>À ò|O“â{ð߀žÃÄö'¤q=#‰å˜O,ÂxžÄð±©EJ,Ráb— ÜXvâÂ@°2E’+ò_ ö¤Wµ"¼àÈ®¨…uD+’±\•ŠÞlVób¶ °X­…hÄ+-!Yi ÅV(B¯²}«ˆ…\D*Ç‘V<Š«@UZ©'I8©åÅO.*]QRêŠLT‚b¢jP¨0EA‚)üqOãŠ{üSßâžð(§I:H)ÅÁN. mˆSlBšÔ¦nE3r)‹ñL_Š_Rø¢–ý·è¥€Å,)P‘J„ŠQRˆ"“.™p¤“E$š)ÁH¶ B,Rbx{À£¥Å.(ÜñFçŠ3¸QÂŒ&a0¢ÑEŠ(©aEK &ÔQ6¢ˆÔF ¢ EJ(tAC¢ TPÒ¢…´- ¡AE (BAB ÇÄV>"±ˆ€¬ Å`^*öqW³Š¹´UÍ¢­Œl`«7EYº*¾1UñЬlUcbª:QЪPR€*‡T< ž\Tòâ¦4è©uEKª*M±RmŠèTB£2¨ŽDp*áPŸ ØTŸ|ûà§ …=)Û¡NÝ sS˜›ÆÞ0¦¹E5Ê) AM d(S!B˜[ÂØ¥Þ….ô)l±KeŠW¨R½B•"©¥…(´)7‘I¼ŠK(RYB‘éH¤N…"t)!H9 >DQò"Ü…ä(¶Ã…¶-›lØ `ä["Ö¶µRŪ–-=Aiê ItZK¢Ð´… ³ÏEžz,ÚÑfÖ‹0ØY†ÂÊ¿Uø²KÅ’^,yñcÏ‹ØX¾ÂÄM"h°¯E…z,Ñ`–ŠþtWó¢¾£õ¯vÅ{¶+Ñ1^‰ŠðÈW†B»jÛP®¢Eu+š\Ô ã€W·ÿ¿ø­ÍÅnn+ea[+ ÕpV«‚´­¥h¬óg˜+-!Yi È(VAB±ˆ€¬ Å`^*öqW³Š¹´UÍ¢­sk˜«*ÅYV*»UØŠ«@UZ©ïOxª=EQê*AT œÌTæb¦91È©OÅJ~*IRH ޼Tu⣨‡ÅD>*qP«Š‚ TŸÇþ8§Æ>0)ãqOŠv S±œÀæ¦÷Å7¾)³M˜ i…yô+À^ íDWj"º‰ÔH®jsP+‘!\‰ àÄW"·‚¼­¨EmB+_!Zù Ô¨V¥B´b£¬ìÅgf+.±YuŠÈðVG‚±[ŠØ¹yEËÊ.PAr‚ ‘T\Š¢ãt ¸±EÅŠ.Apò „p\#‚àT ·Üžæ-ìAob w([¹BÝè·Ÿ¦-µ‘m¬‹j¨[UBÙÉÎH¶:±Ð-‚l \üZçâÖw³¸µe…«,-IÁjN O´Z}¢Òó—˜´„…¤$-¡h¥ A@Z Ïo{x³©ÅN,ÚÑfÖ‹30Y™‚Ì` ²Â…–,¤!e! % Y)ÈNBp±á… ,kác_ tX»¢Å.)p±…ˆÌ,;qaÛ‹ XXZÂÂ@°WÅ‚¾, q`K‹X"¿ ù¯œE|â+Ú‘^ÔŠóèWŸC ÕN¨ÂÆî0pƒ€ ˆ`´CD" À³Fš0a€« ÿà_ÿþô¿B…ú/ºÁ}Ö èÔ_F¢ø¾Åð½Ë…î\/[qzÛ‹Ð8^Âó_šø¼Ÿ…äü/xô Ä^ âðX‚À»ÝÅÞî.êñwW‹¸]Àíh0»ÅØ®.·au» «]XâéÿOøºAEÒ .…at+ Ô\î¢æ­5h¹yEËÊ.PAr‚ ð\‡‚ã[ظž…Äô.!pÙ ƒD\"à H·Ê¾P-äqo#‹uü[¯âÜ…ä(¶é·H-­Ámn gˆ[âÉHJ@² ‘,}cè‹ÿà_ÿÿIúH¿ Eý/Ý!~é ô(_¡Bü)áH¾Þ…öô/©‘}L‹ç¨_=Bù ÈH¾…ð´/y!{É ÚÄ^Ö"ö°½HEêB/G!z9 Íà^oò°•€¼€Eä/qxƒ‹Á`^ ïw{¸»¥…Ý,.Þqvó‹³´]¢ì>aðº×EÖº.¦1u1‹¦Ð]6‚èºEйöEϲ.qsˆ‹˜\\Ââåh+@¹!ÅÉ.8ÑqÆ‹‹\X¢áä ¸:…ÁÔ.!p | [åÞ.ñp·f»0-Ëqn[‹p„[„"Û@Ú¶ª…µT-œ‘lä‹dÌ[&bØkÃXµèůF-oAkz X°ZłՖ¬°µ-E©j-Añj‹M\Zjãçÿ8Ç¢F=1Ò±Ž•Œo4cy£oÓxÆDF2"1y¡‹Í Xðbǃ¬¥`ÄÍF&j1qˆëŒA€b éwHÃVF²0Ì1†aŒ/ˆa|C LZ`¡0š1„ÑŒ#Ðaƒ,A`ÁßFú0iÁƒN ´`½£%)(Áˆ09QÊŒ Ð`Vƒ(ÀIH0Q€:‹þ´_õ¢þÌö`¿ü/Ò1~‘‹ñÐ_Ž‚û¬Ý`¾¬…õd/ 1}‹ä$_!"øZÂнÞEîò/i{L ×@^ºôï§x½…è/4ay£ É”^L¢ñŒè¼/áx.ü!wá »è]ßBîpÈ»GÅÚ>.Åqv+‹­t]k¢ê|SàºmÓh.ŽÁtv  ô]¢çu;¨¹±…ÍŒ._árÿ • \­ä %¸öǰ.4!q¡ ‰„\L"áËX¸@ÅÂ.Ñp6‹~0[ñ‚Þö÷°Æ‚Æ41•ÁŒ® bPcƒå¿(ÅÇF.:1fá‹7 V4b±£÷§¸Å†(,14ቧ J|bSã×ޏÄJ"P1qˆ#Œ>`aó·u¸Ã‚0Ô†  1|a‹ã °]€Â³Æž0¢… $üa'ãwC¸ÁëÆ^0láƒg |`Ãã%)(ÁFº0:á× Ð`Vƒ(ÀBÆ01€!‹ýì_ïbþô¿t…û¤/Ï~x‹ïÜ_~âûHÚ@¾“…ôœ/–Ñ|¶‹â”_¢÷«½X½²…í”/`!{ Ô ^¡ôr£¼äEç"//±y}‹ÈÌ^FbñŒè¼5Eáª/Ñx‹½Ü]îâî¯ux»†EÜ2.Óvœ ²ˆ]”BëÚ^кÑÖˆ.§Áu> §˜]<Ã7Wº¸Í~Fkò3I±šMŒÌôfg£1ߎøÌ Fa2ò1—‘Œ·e¸£,gc8ÊÂFV2™!”É  lec&½5èÉwK¸2Ta’£ ‘ødÃ#ÏxÈÁÆF2#ñ‘Œ†@d2 È@ÈF@21õ¨ŒzˆcÔCÁîÇD†:$1Ä¡Ž% nlcscÓÖ˜Æ|†3ä1”1Œ¡Œaˆc C³½˜Å´†-¤1`¡‹ Ulb«cz£ÐÄòÆ'–1.¡‰u HìbGcZŠÐÄF ò0ü¡‡å ;¤aÝ#!qÃP€0Åñ†/Œ.Àav ¶U°ÂÆ0’a„“ !a£};èÁ Æ 0Z!‚Ñ Ì`žcùÈÀÌFb0%( X`*ÃŽp¿ñ…ÿŒ/ó˜ ù _Íý í¿B…ú/Ä!~! î°_u‚úä× ¾“…ôœ/˜a|à ãÀ_ø(Á@½ä…ï$/l¡{e ØÐ^Æ‚õl«`Í~Fkò3V1š±ŒÒlf“c4 (ÌÏFfz3'Q™:ŒÇ|f;ã1ˆ¸Ì`Ð2ú—Ð »ÄeÞ#.)qHËdÆ[&2Ë!–Y °peƒƒ+;YØÊ£U2œA”â £ðeƒ(MBhÉáFO 2ma“k —Ôd¾£%F*0ɆHü2<ñ‘猌d`ã"&0È]ÆBî2 aK œcüãø0Ç•Æ<®1ØñŽÇŒrTc’£æß0ÆÁF6 1¥a+ eÔc.£”Ä ÅùF/Ê1n±‹uŒXðbǃ[ªØÅ†(ô1;!‰Ù JàbWð€ÄJ"P1ሠ=üaïãžtðÃiH0ÍÁ†n /ˆa|C LZ`§F:0Q„êŒ$üa'ãwC¸ÁøFÂ0q‘ƒŒŒ `Ðc»-ØÁIF J0EÑ‚.Œ`xãÿøÀšFÒ0€ÐŒ,`!cu¨ÓTš 4¿!¥ù *´iU£IOJxÑüFâ4i1£I8h©ÃCð€ÐÖ††´4)!¡I Œh_òøÏl{`3Ξt ñHgŠC;ŠÜPζÆu¶3¡1 Œåôg/£8µŨÍûFoÚ3sᛟ ÙØfÎÃ5Ç®8Í?Æiþ3Eš( ͼfmã2Ù–ÈÌ~cð3‘˜¤ŒÂf#/¹}Ȉ^2â‘—Œµèe¯C,™dÈÊú†WÔ2²!•‘ ©eH#)’LÊ,FQb2€!” œ„dä#&r3Éj†KT2K’X d€## ÈÆD~2È ‚¼dãçÿ8ÇÁ†> 1âQŒuØc®Ã|ãàÆí7h1­1iŒgÈc>C*ÉPÔÆ ®4ü§à;äiß#NcsÓfÆ›64ÐQ¦‚0ôi‡£K§]8Ò·Æ•¾4¤‘¥$&i0#HëGXÒÆF4wA£º °hÕƒF0°ÑS†Šœ4Iñ¢O\hzãC(@И„À4¡ å ¤h#@S˜Ï܆~ä3ꡟU øPgƒ=3é˜Ï'Fy:3»ÁÞ ì4ga£:,Ñ`Îe†s,3‹QœZŒß´fý£7>¹ðÍ—Flº3Záš× Ó4f™£4 ðÌÏFfz3'Q™:ŒÇf8Ã0å‡(Ì †`l2óÁ—ž ¹Ðe΃-Ån(Ë9YÈ2ÁÁ– ’œl”ãc{ØØ†Äl6 °l ~Lkòc^5ñ¨×a†» 5Ï®x p k…[’ÜÖ²†µ”5£A­ e°k-ƒXÖưÖ†°5w«¼ ZÀjÖV°ÐÕT†ª¤5KÁª^ OÐj~ƒS^šðÔ¥†¥,5 © D|j#ãP‰„HÓðFŸ‚4ò±§•9ŒiÌcM›lØÓ;™Ø4ÂA¦ .8iqÃJ­UhÒ…Æ”.4“a¤› "iãG¿=øÑÄŽ 4d£$ h°DÑ&ˆÐü‡à45¡¡­ ähO#AÊPÐ:FÒ4¡  ýÈgîC>‘ôˆÏx†{Ä3О€ŒñHgŠC;qÛˆÚ{FÓÚ6•q´«¢àq÷ xHãG‚8Ú±ÆÕŽ3ŒqœcŒMbhâÛØ8­aÅk·”u¼£­Ojxë.GYr:À¡Ö­ÐunƒªÅV(ê‹ÇT^:˜ÔÀ£¨uC¨;AØééGOJ:oaÓ{™€tÌ¥˜,ÀéFÇJ6:E1Ò)ŽŽôtw££pèžDð:ÐØ„ht#C „ çï?x9òaÏ“yxsËÃÈî@çFG:29ÅÎ(Žnìswcšóטæ—G4º9™QÌÊŽcüsã˜7Á¸åèG/B;‡Ü8Žßlvûc·,¹`í«Çm^;^qÚóŽÕ¨v­C´¢¥í GhJ;5ÑÙ®ŽËvXã²1‘ˆì`‡c;ÁØvÀôv£¯§}8ë·Ç]¾:æ!×1¶hu³C­h ëXx:»ñÕߎ«Üu^ãªaSêfGS2:1ÔŽ ìuc§¾=ð齇Mì:fÓ0–`t³¥(é‡Ht"Añ…Ô|.£àßøøGÀ’=ù¡ïÍ|{àƒÞUò¨÷v»°=ÑîˆrL{’cÛäß öÓ‡¶œ=©ñíOh${A#ÙZÊÐö1±ˆ=Áëþ]˜zìÃÖж€õˆG¬B=X±êÅS z˜cïx@ûœ‡Üä>ßQöúµ}¨Ãì°e€ûGØ>¸Aõ«T}Z£ê?QøúdÓ >¡ô}¡ô}£çµ=¨ùÎÎp>gó8—Ì|¾cåD* ù+‡É\>?ññÿ¤|m#â¡ø‰ÄH>Áð®ƒ||ãù­ÍhþLò`?†ü4߬~ýc÷Uº¨ý©‡íL?b‘ûÕè~¯Côä§ ý Gèj?;ùÜËÀ~^òs“˜üqãˆ?áø—Â`~ïéHûÔÇÞ¦>êA÷R¸8}ÁÃí_jøû2GÙ’@P€䀇$¼ áÃH@)H„€<$d !3ˆœ@bþ$ñ#þÚöÐÿ—Güº?Úáþ×ô`£üiãHþû÷Ø?²Aý’êœTãùßÎøþRGò’?ŒÁüf@Œ‚dt {¡½Èî@æ06ȶD 5 i©!ˆ @À’-hkD Ý Vé…H*@™‚Ì$ DS B™ïHz@pâ‡D€Ò$â /S ˜@IÒNmƒh¤È ÖA†H42A™Â Îc´ƒ¤p Ãöˆ/´Ar² •Z¸‚ÕÄÿ ¯ù`ˆ+AM2 iQX‚ŠÄŽ œqÄH&"A'² =G0‚9„6 ‰±!È!Bh@˜ „Àd%m!+i 5ÈI®BE¢-ެ„ud#.!qŸÈDþB’ô„è„'D ¤!! È@NA÷‚¼{ìƒßdL òasÈ;žAÐrƒr(ƒ‘D1Ô!Ž¡ IHbJC `ÀH†D/•!|© ¿È]þBå(·L…ºd-$!i! )ÈYNB¿‚ü­ì…od*å!W) ˆTlB›’ܣą$(t!C¡CÈzCÉ"I|d;f!Û1­ÈunC£¢æ,‡1d9!ÈqpðC~"ñÝ”†ì¤6¶!µ± ŽHlrCX¢ÅÓІž„4^!¢ñˆ”D|Ò#æ‘xˆãÄF¡"5 ‰ŒHDWR"º‘àˆŸDI""Ió‡˜D1Ò!Ž‘ ˆPäB "QVÈ‚¶D â o¼ˆäSž"œñ»È¥ÞE(²)E‘GpŠ;„Q_"Šù,¡`E¢( >؉öÄO"x9¢ˆDݲ&í‘5x‰«ÄLÈ"fAH˜2Eí’/l‘y ‹Èd]­"íiLº`EÉ¢.Mpt‹ƒ¤[n"Ûq¼HµâE§B-:g‹8¤YH"ÊA&H±2EÂ,¨PB„i—#L¹:ÑÐFˆB4BŸ¸ŒýÄg?#9ù¶ÈͶFbÂ3–¼Œµäe2#)‘ ÈÉF@b2ÓHŽšDtU#¢©éˆçLG4"9¡ÊLŽRdr#±fHã2G¢8uÁ´Ž ¤o×#~¹ÐHÞ‚HÒ@‘þ@ò#ø™ŸHüúGà?õDª$|Ô#æ¡Èø®Gº‚=Ôíh„ŠË$VY"™ÉÎHDè’$ì‘'dˆ¾$Eñ" PHz²CÕ’¸åÄ•¢$­%II*JIJ‚JTOä’$“•$œ©$¹‰%ÌJòP‡’€” Ÿü$ÿá'ÓI>šIíOhyL“Êd«Í%^i*ÍÉVnJ«¢U]¨•D„·!%¹ -© mHK_RZú“ p˜K„Áø&Á3LÉšfñJ wp;¸L&6›«ÀÕàm6€L&y<«ÀÕàp°8X° XK%«ÀÕàl€6@L&ÙìyÀ¼àd°2XÐ è¯WÄÀâ`W°+Ø çóƒÀÁàd°2X¼ ^ßoGÀ£àR ) ŸÏyÀ¼àd2H´ Ú¯WÄÀâ`ñPx¨=,–ÄbGÀ£àS)€ Ïç~@¿ d°2X¤ RápÄÀâ`çðsø9üþÔj¸ÁÜ`Gp#¸ì vÛmGÀ£àU°*Ø çó@Ç fp38¼ ^‰Ç@ã Ûpm¸7p¸ ƒ†ÁÃ`çÐsè:¤RãqÀŠàIà$ðì v …GÀ£àX0,T ªùü’ÀÉ`jð5xÌ fóyÄÀâ`vÀ;`/D¢ 5ƒ"Á‘`ÎÀg`4P( S©ƒfÁ³`Ûpm¸8l6K%ƒ¶Û@?0˜@ W+.À—`L&H| >z½i€´À^p/8, –Y,«ÀÕàjð5xÌ æ\®íö€~P?(! †Á`‚SA) œðNx(Ìf —K‚¾Á_`µðZø/ † 'ƒ‰€ÈdH2Ün ÷{ƒTÁª`ÛPm¨8H$|>ãÀqà?0˜ÐèW+€ÀK°%Ø| >R©`À°`^p/8 K%’ÀÉ`jP5(œ Î`°ò€ù@‚àAp"ˆD ƒ‚ZÁ-`œðNx(Ìf —K‚¾Á_`µðZø.”J Ãá‚ùA| ÂPa(1Äâ ¼^K¥€Ú€m@8l6+•€â@q 9ÀàÌæ$ÀŠàK°%Øô ú `À°`Zp-8œ Î ’ÀÉ`i 4ô úw»öÀû`ƒðAø"ŒF ƒ‚ZÁ-`œðNx(ˆD G‚º]±X€-|¾ _¯‚æs¾Ð_h18œ ÇcƒR©@ÜÐnh:(Ì€f@8ðxètóùÀŠàI$Èì vP@¨ X0,D ¢çó’ÀÉ`j`50L&w»öÀû`ƒðAø"ŒFú}ZA- ›pM¸(d2 f3¥ÁRà­0V˜+ìö O§‚ívÀÂpa82\. ŽlA¶ æ s ŽÇc€ÊÀe`5€<óù @† Ep"¸ì vårGÀ£àX,d 2çó’ÀÉ`jð5xL&w»öÀû`ƒÀAà"l6 ‚‚Z-@›MÈ'Ìæ 3‚’I@©pT¸+äò o·ƒƒÀÌÀf`5L¦ Ôê›ÍÀ&0 ŒFÇc€Ã€aÀ2°X<½Þ€üÀ~`E`"°Üî»]GÀ£àV+Hœ Nçó’ÀÉ`jð5x f³õ€úÀƒðAø"ŒF ‚S)À—°KØ'<ž áð‚ŒÁF`«U€-Ôê M&ƒ>ÁŸ`Ùlˆ8H$‰DƒÍæÀðø Pc1€˜ÀL`,p8 D¢+•€ß@o 9 ÐÌæ?€ŽÀK°%Ø| >x¼e€²À^p/8, –¯W¼ÀÞ`u@: Œ/‚Áà‹ÀEà$  kµ‚iÁ4à P*\. r¹Á‰àÏgÈ6„B ƒŸÁÏàîÐwhl6ÿÿ€†@C &0 ŒÆÇc€±ÀXà2°X øü‘È€üÀ~`Ep"¸øü»]GÀ£àX0, çó”ÊhÐ4h( ”+•ã€ñÀ~0? ü~›M‚9A ”€J@'  Z-ÏgÀÂ`a03d² S©ƒmÁ¶àá°pØ:-–€`À0`P (üþÿÿ€˜ÀL`&0 ŽÇc€ÊÀe`8ðx¬VóùÀŠàIà$ðì vWÀ«àX0,œ Î;“ÀÉàjð5xL&w»ó@ù €@@ !0˜Õj‚^/@£ QÐ,@ Ùìƒ A Îðgx5L¦ ´Ú†ÁÃ`ëuˆ”Ê7›€c@1 ° Øüþ#€˜ÀL`'  Žñx€ÊÀe`8ðx`°óùÀŠàK°%Ø ŠZ­Xà,pœ ÎK%’ÀÉ`jð5x4šßÀïà ?"d2 Y¬‚‹E€¯W€.  ÁŒ`ËÀeà4”J ŸσˆÁÄ`ìÐvhL¦ètMÀ&à° ØœÎÿÿ€˜ÀL`&0 ŽÇc€ÊÀe`4À`<óù @† Ep"¸ì vÎgGÀ£àWÐ+è çó@Ç d°2X¼ ^ÐhÇÀãà{ =!x¼ J¥‰AD «°UØ-ˆ ¼Þôz@ÂaH2< ú}f³ärTl*6Ói€M&€ð øl6ÿÿ€@€&0 ÄâÇc€Äb2°X<Ç€üÀ~`C@! \®»]9œ€Qð(øü þÎçyÀ¼àbP1(, –¯W¿€ßÀwp;¸ Ìf -–‚}>À© T+Àà _¯‚×Ákà¹p\¸0@ ‹EƒAÁ àÛmˆD¨"T!¨Ô¥AÒ¡e²ÈL¦7›€fÀ3`P (üþ*˜ÀL`,p8 Ž+•€ÊÀe`6 <óù€€@Ep"¸ì v»]GÀ£àX0,¤ Rçó‡@àd°2X¼ ^+•û@ý Ž€G@&À` 3‚¥ÁR௰WØ,x< û}‚×kÀÀ`H28 (”oA·¡ ˆÐ‰¤DÒ- –Šö…{@ 0˜Ünx¼fÀ3`ðø €@ª€U@, P Tª+•€ÜÀn`8ðxètôúÀŠàG@# ì v^¯X0,œ ÎK%«ÀÕàq08˜„“I‚YÁ,àNˆ(Ìf —K‚¾Á_`¯°WØ+ìö kµƒ Á„àÉÀdà5  »Ý…©Ôƒ¸‘ÜH8Ôjs ¹€4À`p ¸t:žÏv;ðø 0˜u:€±X€,H ¼Þ|¾ãÀqà9ˆÌæ'ÀŠàK°%Ø| >ƒÁp€¸@`ð0x´ Z‰àÀð`… BÐ$ tºtÁ:`£0Q˜*\. ²Y¶Á[`³PY¨/ † ,,–@Ôðjx=`°R )‹ÅÁ´ÚHX,âqMÀ&à° Øl6›Í€~€?@!ˆ ŒÆÇc€Ãa€3  |¾ÈäãÀqà?0˜ü~a0.À—`Qð(ø çó €Ð@r9àð.,Á`“IÈ&x< Óé‚FÀ©pT¸*\. û}‚Úm@½@^ 1L¦ ¹\ƒRA© ÷{ˆ}>ŒÏçˆãq€ 0˜ètÀ€e€2À l6½Þ€À?à(0 ”J+•€ãq€3p¸ `°Ç€üÀ~`E@" ì vÌfGÀ£àY°,Ø ˆívÝÀîà~?!0˜çs‚ZÁ-`œðNx( 3‚¥ÁRà®ðWx-L¦ ­ÖƒÁ„`Æ€c@3¨Ô f³‚BA"‘HD0"‚ Á2@ @ À`H¤MÀ&à  Ðl6€¬€V@* ŽŠÊÀe`8àpôz+.À—`L&H| >ƒÁÀÆàkp5¸€Ûí‚ÁàŠ0E#øü ?Ÿ‚\.œðNx(Ìf šMÏÁgà¸\/Š 1ƒ&A“ Òðix6Äb …n‚·@ð@x @ Ói€6p ¸Ün‰Ä€fÀ3`ðø¸\c1€°ÀX`,p8 ¬VÒéÀŠàG #Ð\ ®'“a°€_0/˜8 îwÔê{=È ˆDM&‚(Á`pH8%¬Ö Ôê¥R€¯°WØ-Èä ÃრÁ„àÈdH3¼Þ E¢ƒmÁ¶àÛpm¸0 2À àðxL¦Ói€4À`p ¸är›Í€y@< ðø ŒÆÇc€Ìf8ðxÌæX,1€˜ÀRp)8 çó’Éip4¸¼ ^‰Ý€îÀ|à>p ôz£Q‚AÁ àÃ`a°'°Ø ްAX ¿ _Ð44 W+ƒnA· ò yVŒ+FV«V‚+A€Ž@5|¾ ?ƒ,Á–`Ò0i8\.f³´Ú@å€rÀ;Øì …ß‚ïÁuº€ÇÔcêj 5ÔCê! ð†x-h´H$ ÷Å{â}>€ˆdD2$³Y‰!ÄâL¡&PÈ dP †G£àá0p˜3h´ ‘ȃ‹Åð‚øEü"þ‰ƒâñA€@X¬o7€€@ L¦7›€N@' ° Øüþc1€³@Y 3àð@ óùÀŠàK°%Ø| >C¡`À°`^p/8, –O'«ÀÕàpÐ8h Ðè4‚Aüþ®HW$<ú}ÂÇác1¶ø[|.{=ŒÓFi¡¹Pܨh04F #KB¥¡ˆH«`U°.1†óÃyâÛQm¨ê,u*ŽGûƒ}Ád@² P|(>Y¬„ B¡ðŠxJL%&ì öþB!Ú í_¯á[ ­ÐTD*"Þ oÒér€¹@`Ø0lÎ gP¨¼Þo7€4À` 0˜Ün|¾p€8@%àð Ž4šãÀqà?0˜àpW+.À—`M`&°| >ƒÁ‚«Ui´È`Ì0f!Öë F…#Caˆ0ç„sÂAÆ ã­Ö„Âa¤Ò=‹ÅŽ=ÇâÅ¡bÑ7›Œ3?Ÿ‰Íæ„Uò*øÖ\k.|¦>SxÊL&å r†yC<¡eà²ð“,I–/‚‹·Û‚V1+ÿøüTÜ*nç‰sÆ÷Ã{â6)j(5#Ê‘ï»7ÝœívŠËeŠ(íTv´}ª>Ôðx¿Ã‰aıÌ8æÈäÆc _F¯£‘AÈ¡y@¼ žüO~:o7Ð_¸/ÛQŽ(¦íSv§qS¸¨»]‰îˆ÷DAê õ }ƾâÙql¸§Sˆ6œNWˆ«Ä!‰‚ª U&ƒ“A¾@ß #„ 5ƒØÁìa¨Ôd@²7a°œƒNA¥lB¶!ïÈ÷äuê:õÁàeײêõaÛóŽùØ¢,Q I…$SB)¡(K”%ÓézN ''N“§.¡—PÌǦcÑI˜¤Ëø¹ü]•ƒÊÎg µ@  ë†uÂR_)/›Mͦðcˆ1Ãï9÷!¥ÒÅþ"ÿ óvù»‹íÅöÊVe+-§–ÓÇçcó±—L˦I‚$Áǃ%’Áž ÏWÆ+ãŠ?Ã\q®8q@8 ÓiˆÐ„h@P(,o7€$€@€À|¾ÌæŒÀF`*@ ŽìvÊÀe`8ðx¸\óùÀŠà¥ðRø´ ZÒiHC¤!ià´ðp8 YÓ,é¢ìÑvjý…~Ãø©üUh4J)¥КˆMD(þ»Š]Æ&£TLú&|’Id ²b¶ñ[u¡:ЧòÓùZ­E=bž²öé{t‡¦CÒìËve¼Éždш‰D®öW{Q¯¨×ÐÎ(g+•iδç'|“¾=žÞÏpÆhc4&J%ÜŒîE0¢˜PÀØ`jرlX™õLúžLO&&Fs#8Ý naè0ô² YIó$ú¥R%l¶b1O±'ØÅ bÐC!„P( €AM¦„!r¹Š !ðàxpxò€@ €üþJ%™@L ,p8 ŽÇc€·€[À2°X<Áà‚…BÄÊ"eg¬³Ö‹EŠ—§‹ÓÄUr*¹¿@ß ÝnÈ>¸ß\r²ÙYlΆgC.—¿ÁŸàÎ¥—RË·ÁÛàó’yÉ:ÔjPUØ*ëñ1ø˜ôz>N_'0Y8,œCz!½Bý¡~ÍfÈ/Z·­] „%è’ô9œ„NÒih:4 ‰…Ã;¡Ññ¨øÕF£†‰CTª Ó‰ƒCÏçÎí@v >@_ 3 Ž„†FC#A› Íɤ‰ÍÒFé"W¹+ÜLÔ&j¿È_㿊™…LÂ(N”çÌs䲨á¬pÖ6¡P”k 5…óÂùà˜ Ìe2ƒ(”B¡ Qs€¹À_œ/Î8U\*°åÈrãСèPúx}o7‘^¯ w>;ŸýŽþÎf'3o‰7ò±ÙY C„¡ÆÔ£jO7ƒ›‚íÁvùØ|ìAn ·ÇWã¬pÒ8i/4—šL f/½ÞŒiŠ4ÄþD"8ÊÜen¨÷T|QŠ(Å2M™&ÀaÀ5 Ú†ìêþu?€Ÿ°«ØUå›ÂÍá Ð?D¢B! †ÁððøxVÜ+nGI#¤I2$™¢üÑ~aM0¦˜Ìà°Xôz•J€I€$À° Øüþ&˜ÀL`&0 f3™@L »0]˜©DT¢ÝOé‚ôÁ¸‚Ü£6Q›#²‘ÙN ‡äAÒ ýG~£ÅQ¢¨ÑRh©4Ñöhû5bš±Ió¤ùÑN§ T¦*Râ¼q^7üÛþná§pÓˆ¥ÄRâhq4>¼ß^pð˜xLŽ.GA» ÝÒÛ©mÔJ#½ÍÞæä¡rP¿ªßÕp¶X[+iÑ´èçÔsê=åÞòïOw§¼¬V-ï–÷Çü£þOª‡ÕD &ò’yI7ÙÛìîT7*õMú§/°—Ø;i´Ð „nj74õzˆ9ÀÜàmžöÏy˜ˆÌD=3™™Ý î‘BX¡*v™;L„ZB-‹€ÅÍ"æ‘oÌ·æ @†žg3ÆíCv  p¸r9€ˆ@RÐ)h,€@O'Çœ}>†HÃ$bÉä„çBsµvZ»)DŠ¢© Ô˜/L³¬Ö 1Ö˜ì.¶[žŠOE%"’“Y‰¬è–tKÙˆl¦!S'(““ŒÅÆbÝunº¹#œ‘ÍéFô£¦µÓZÿ©ÔÃ%a’±ÜHî$ÍNf§[»­ÝÀá pÍ»FÝ£³Ù‚üí~v·œÛÎmÒé¸5ÜøT|*LT&*öIû$òù 8„œ:êuápƒm!¶×»kÝ».—˘e̦ R×àkð@›`M°rÈ9c‡‚ßÏoç­5Öšå±bذìv±X‹1r˜¹IGT£ªqi8´|ð>x™ ̉Ù$ì’@ŽšÐMh"íQv§Æ“ãHtºÁ`€MÀ&ఠؘÌ)€˜ÀL`?`°" ìö>ÁŸ`íðvø/$’ ¿„ë‚uÄÛ"m“ú}ý>è¼t^0R˜)L±–XËeá²ðÓßi難•ÃÍ–€ÊóÝyîÂÀa`7˜ÌÉ÷äü4–KJˆ¥NM'&‘„¨ÂT®× ~†¿<÷{›†ÍÃl™¶LäGr#»H]¤0>h4¶B[!$ ’L•æJò)¹f\²åPr¨6™[L®Ù·lÛ¸yÜ<ÓÀià7üþ³ÇÙä²HY?aŸ°ÂÕ!jn§·SÕÇêà–pK5·šÛÍ"&‘È ýÈ~ä>P_(,¿¶_Ø#`°ª UC !t€º@FŽM &…G‚£Ábð±xrP9(]˜.Ì?ŸƒÎkG5£§ Ó„ãšqÍ8¡œPηFÛ_¯ŒÏmg¶²¾™_L”æJs^Õ¯jó¹yÜÅ¡bа±X„h¦4S'¦“ÓCNa§/6÷›|¾^á¬pÖ7šÍô7z r9 Ò†éN'“•9ÊœÆúc} …G©#Ô÷ŒûOõ§úå!r¸.œM5æšóvñ»xòoy7Ãð¡øRݹnÜCÞ!îêZu-À à P¨Ün›Í€fÀ3`ðø ( Ãa‡²Ùu:ˆ£`Q°‚ A¦SÍQf¨æ4sZ5-¡çPó¬Uæ*óÎMç&ä²rYp ¸´ÚŠÅ5@š Ö kP‘0H˜7²Ù‚ƒ¥áÒð±TXª#€À LF&4½^ާS¡PÁñ øÏÚwí<2ý„~Áí`ö°Jø%{×Yë¬ókyµ·[È-â¦ñSÉÕäëÔê>ýŸ~ÏŽ'Çï)÷”óåyòÁ­ ÖŒ‡ÆDªTú;}¸|\>.Sw)»\-®èÇtc»÷ûMØ&ëòíùvå¡rжÛ n'“M¦ÎÎgg3‚5A¡`°¨ìTv`30¹ô\ú&ÖƒkAd²0¼^Ç‚f´ãZuY^¬¯^¤¯RNg±žØÏlžÏ+•‹Cq!¸3ØëÉ9äœþîwïweD²¢G§#Ó’ÅIb¤Dö"{@€ :þ õ¶úÛiA´ Ùlº2ÝmT&ªŠÅú]}.½ÒžéO¼‡ÞCº9ÝßµoÚº1Ž`÷0{dݲnÓ1i˜·(”8'œÜAî!ci±´×é«ôÕ*ŽŠÅ f\³.[Âmá7âûñ}qj¸µPܨnOQç¨ó§ùÓüíòvù=ž‹A `…/6›©ÔŠé¡tй…œÂÏWˆ+ˆáÄpÔj4'ÚíþæÿsÃÑáèø–|K:ý~ÎÃ7a›‰-Ä–×Âká7k›µÍdf²3ááÑW«Qú¨ýVk5“Éz†½C`þp4Ý*n”¹\‹".‘HÁd`³où·üVÒ+iþ€>âßqpÈ c÷Ýûîú}G¾O'FÇ£cM…¦ÂÑhƸ!Üî£wQ»Ìåæs („”>ñŸxÍÖöë{J!¥σgÁ¹z½í)ö•gгÅUõªúÛ*­•W¥‹ÒÅ›æÍóEÊ¢åKÔåêq‡8Üg23™* •Çcã±ò\ù.|†ÞCoÏ‚ç¾ÿßîʇeC‡að×ìkö2§™SÌõvz»eá²ðéÍtæÂ !Õ×êë˜åÌrÓÁià³.— ΉgL…¦BØ,¬VTË*eJò¥yJ ¥Hï$wÿX¬aê0õ6¸›\Mn&·þhÿ4LR&) ‰@. NòWy+~¿NÓÐiè1ɘäÌèVt+«)Õ”÷×{뾇C7÷›ûf]³.Ëme¶ÔµjZµzƽuƺãOV§«PØèls©ˆÔ|†>C&‰Cí¡öÓˆÉÄdôÚzmö‹{A¦àÓpŠ8E(û}ƒ¼|ž>M†vÃ;áðØel2¶j›5MßÖïë¾éßtå·rÛ´šVrë9uQ>¨ŸHš¤MSré¹sQ‰¨Äm6‰(ç”sÆ6c/Þ÷ï|$>%€¾ÁŸ`Ï.— äÉòe€ÎÄ?b°Ûxm¼&6¹À\à.#×ì‹0˜Ñçhó·[ˆ´Z¬òºy]Sõ©úΗgK±›Hͤ"–Jø|<•^J¯ W…+¦eÓ2ã q†:þN…B„z=1ǘ㿀ßÀlÈödz›áMð¨•TJ¬™VL«ƒ‘€I/—‹Îé§tÔaÊ0äæseˆ²¾`Ÿ0O·[MΦà{p=¶{[=­G&£“ŠñÅxâq»I¤Ï!7›*Ñ•h¬ŠVE'î÷ Kå%òyF¼ª©UTΧS‹‰ÅÅVƒ«ñŽxÁDà¢p (“űâØè€t@6½Û^í?VŸ«*É•dÝ/n—±•ØÊì®FW#O½§ÞµØZì*Á•`Éàð`90>NŸPhè4séôN‚§#Š‘ÅCÇáãð8›ÝîÆïèwô9‹ÅVÀ«!ŒÄyb<­“ÖÉë õÐzÀÉ`d© T'éÓôéœÔÎjJí%wVЫhUŽ*ÇÓÊéä±6X›%®’×E£¢ÑÑ·(Û”Œé˜tÌ6ä[r,%vºÚ]m.°qX8«•ŠÊAE ¢m@¶¦S¦“FÕ~º¿\¿_‰&9“Ç`c°1?XŸ¬3n¶ýN~§8ÝnK&¥“½Þ¾é_t®vW;+ŽÅÇb± X†©yT¼®tW:* úƒýóŽù¡aP¯å·òÛÐéètêúu}85ÜíF¶£[ÍŽf¾H_$+$•’KJ5¥Ô}j>³ Y†­êÖõkõˆü´Z æ‡ó?ö_û/8—œK³ÙŒét€5š€Ë‚UÁ*¡µPÚ¤RN¥ ’†JTõ*z¶É[d·Ž[Ç,ä–rTêô‹*E•Kƒ¥Á¶ Û“çIó %„’¯wW»¨1T©d„2)áð‚?A£]Q®©ù”üÊúY}-X ¬J e±ø‰{ÝuÊ]å(ï”wÉ: h)4‡µCÚ¢ÁÑ`ç´³ÚZSA) À'`ÏN§§S †„p’8Hó`y°4XZ,+KÅ¥âe ²¤FÒ!5Pš§Qã¨ñóØùì´Z?ÇO#§ØëÆYã,¹ë\õ¢ƒÑAè Ôj A rÈ9dÆLã)÷Äûâû­}ׇ: l¶6Z¤ÝRn—bK±G £†.Ói„(‚ùA|¥ãñŽ¥'R“[i­´‰\D®*L•&œ³NY†LÃ&p?¸‹ ʼn>ÔŸiip´¸n¹7\ž‰D†²³YYjxµQëOZyÓΜ(áFö7±»ÍÞgS:™dË&K2Y“Lše³-—¨½EÈ.AmKjZòזܶåÍ.i[ ØT2¡”¤¥%(ñGÊ>Râ—(©Dù'É2I’J’T’X’Ä“$™' 8KX“Pš…(ðϬíp‹„4!¡È6AL‚d#!€F’4’p“„Ú&ÕèÏZŠÔ[úߨcÃþGò<±åލuC™ÈåG*9ñÏŽÜvãÙÉD ’„Ñ&Œ8¡ÅÈþLšdÔ]¢íiëOp€á§ #l`цŒ2Á– ˆdC&0ÍÆn5Qªôo£²üàC‚(‘Dä'!QÊŽÀ†3™œÍÍnk°Ý†üwãÃbõ¬É&IF0Ö®µw ¸PƆ4.Áv 0Y‚ºЭ…l,!a d["þðËFZ6q³Ž¬ucö±˜J¢U@¢€,~ ðg£=àÇ›<ÚPrŽ$q&Y2ÊTR¢Ç–<¿5ù³QšÀn®tü'áCR‘÷¼Ê¦UFº5Öö·¢Ô §…<'q;‰tK¢R•Dª&4 Pâ²¹ÅÎ2a“ ¸mþñÈ.G‚<ˆœEU*©t  eS*›Ü‡{;ÚP:Œ¤e&0 BRÃÖ¾uó³-™m»mÛ®püGâCv²ÎfsGú?ŠdS"]è‹DZ Áà?õ¨€!¡ HqˆªÅV.ñwŒäg#hú‡ÔDâ'ì—e1)‰kË^cƒ Ùc;‹„\%É.J7QºÁÖ¾5ñ³)™M¾mó°€ü÷çîr´Ôf£IÊNœDáð€qƒŒ°Õ†x3Á¢ mCjpëˆ@‚:ОDò,` @Z.pä‡$?ñÿ‘ÐŽ„ò'‘^Šô`£Ô‡H:AýÏî‹X%Ñ.ŠDR"Ç–<Àf3០úoÓÁž (E6)²‡”8‡D:pã…ü/áC D‚$°uƒ<àÂ3Áž yx#ÁR cÐæˆXBÂf0¯Ez1ÁŽ pcò‘ˆÔN²u•Ô®¦ 0Q©ÍNtã§ »EÚ`Ó¥u+¬Õf¬ aEÚ.áÇ<ÁæP‚„_âþ!q †ì7am hKBZp{ƒ0€ªP$A"€D¨@Ó˜@œ…Ø.Á¹ È%Q*мUãˆÞÆö>Ñö‘ ë'Y^ ð`óš¼ÕçZ:ÒÐh&m3jrS’ÕVªÄ6!µ¨HrC×Þ¿hCFæ7"ÐnCrP²„€$æ0-Án IÜàf0€ä PJ‚üàñˆJP`³°5ùÈ“˜*T 0aƒxÀûGÚF²5“ÈžE‚,‡ 8kó_´í¨&A2:QÒ›”ܪMRkz[Ó˜ÜÖæ·9ñϘ|Ä0á†*1Qˆ EÀYÂΰƒt «X Á`3P €R€Ì€DÈ@å(GB:Ю†4ó˜’D’*qSŒ4a£}èýèGB:øŸÅ‘,‰‹Ì^mckðèCBBÒäï*õW«©]K'Ù>ÚVÒºá×Ù~ÌBb,1a‰HЀ\àðƒp€¥(€ô -À>ð€ŒÐ.‚«X7Aº€Œd+!¢ |ƒä$±%аUƒ¨áÇ@¥(‰j Pdƒ$ÌÞg©=JГTš¨)AJîWr÷—¼Í¶m·•¼®ýwì Ihs ˆLAêP`ƒ°•ƒˆ@§8Àî@*ì`/x `à` |à*P °m„\"áZ ÐiCJ€ü LJb¶°È†D9qËP‚„›$ÙJŠT\Bâ¤Í'8ÁôO¢‰DJ%•,ª@RÊPÁÆ4y£Î-qkÒÞ—h;DF"0 €L(áF áx3Á@ ‚°€ä HÂF°µ†è7B˜œÄæ-Án 4i£ÈA˜M’l•Ä®&0‘¯|wCº Õ©Hv“´«õ_®Áv ®esoxíWj¿ùÿИ„ÄMbkC2… (IÂN €l\àd @z€D `@"àYÈ Á @Z¸Á0 €^‚ôÐæˆœDâ‹X½Åî6Á¶¨}Dr#‘@ÊYâÏȆó7™ëOZ‡$9%(Š Q–À´ Žp³ÍžmX2Ä Pœ„äNbr€Ü@*ùÈ,Abp;( @(@€$p€Àx@BÀ€ Œ`0€Ð~…(!Ž pyÈ$!!  UÀäG"A" t“¥3)™t‹¤g³=œ¸åÇí?j.p˜äÇ)½Më^ZóX²Ö&±9íÏo }5!©HºDB"²a0‘ƒL`’@º`h@@@@D &0ˆ 5d ЀC€¬ 5˜„Ä,Áf ügã»ÙH‚Mh•¤­& 0i®tw#¹ ÙÉH"w“¼¬Ub®åw,ºeÓr›”îWrÀF1NŠt|£åØÆÈÊFAY È@ `[è@KX P `€ ` ¸ÀOxð  U' 8\‚ä`ãŒDb‡8½Eê6Á¶°}„v#±BJZbÓ8ÉÇ8ïOzˆDB%]*ê7QºÈÖFÁÖ´¤n9qË×¹èGG>9òw“¼¯ezp›ƒ€ŸøÐà€ `€ 0€ð@rÐ.‚(@¿ø?Aú0¡†H2AêP’„”+1YŒdƒ  HKX•$©%ë/Y¥,tæ 9ÈÛFÚmh©•L®%q,ˆdCe›,ëX?iûQˆœ—dº»õß°ù‡Áz ÐGB: ðg‚@]è ÀnÀ0€(@ ¤ H@à PhAØY‚Ì܈PB‚xÀ¹EÊ5¡­d{$b#= èXòÇ˜ÔÆ¦ç79èD€4¡¡ ÏFzNRrštÓ¨aC ‹TZÀV·Å¾/Ý~ìycË?YúØV¸AÂ2y”àǀƊ4RH’D¼eã:Й|Ëæ·5¹ÄŽ$vã·<ùè1AŠ&0€¥µ-©ÛNÚ“Tš¬`,åg+´]£ ˜dËf[4ñ§Än#”œ¤÷g»@6°¨…DR¢•ØöÊVR³@šügâ ±(!@Á!Á€,Ô èÀ°€D @r°-‚à»Ø>AòðŸ†81Áä ‘ˆ*ÁV tc£—¹È6JrS“Äž%>)ñcK]òï˜ÈÆFˆ4A¸ÄsãŸtó§þ?òÐÆŒ¤e$Ñ&‰ M„ ¨5A«å_+s[šüàÇ83Ñž{kÛ\ é7I¼äï¼}ä ­8yÆV2²:‘Ô¹¥Í99Éш£Ïx7‘¼Žäw#ùÉHzHBB4™¥(ÁYJÊ[RÚ˜ Á]2é­Mjqˆ´í§Ì>b Ð^‰DJ#õ©hKBuÓ®¤…$*õW«4Y¢ë×^Âæ2½•í5i«o›|ä—$»eÛ/n{t` (QE(1ä$¢¥3y›Ïš|Ôœ¤àTB¢ð‚ì`ƒ°€Œ`¸@*Ѐ¼àKX€ä 0QƒpðZа݈XBÂ{Ø«Å^.qsŒ€d]èæ‡4=¡ítƒ¤c#*‰TO2y•¨Ž,qx ÀcC(ÑFã7ÏÎ~yÓΟüÿècC2‘”“Dš&4 Pz Õ¯…|-Ån+î_sXÚÏx5Ý®îp£Ýò7‘¾á÷P‚„;aÛøÇÈÖF²ß–üã'CÚÓΞu¯­x™È)L ’ h‰¤M$ kKZvS²¤¥%*ýWë7YºìWbÃ2Å–-5i«o›|ä§%;eÛ/l{d øOÄþ'ñá ¢%39™Ï’|”˜¤ÅT*¡`˘4ÁI H>ô  ]À]è€Àˆ@" X Œ `x1ˆ0…$)!˜ À|à!ñ‰@Jƒ®p.ñwŒ¤e#d èÇF>1ñ”„¤j#Q,‰dOÂ~¨å–,±yËÎcÃHÒFë7YÑÎŽzcÓ ¨iCJ4 “¤&4êPª¢¯Å~-ÙnËó_›˜äÏVzµí¯np+¥(òW’¾é÷PS‚œ;áßøÇÈÚFÒß–üãgCêSÊžU¯­}›lÚ0Ù‡|;â hDz&ñ7ŠŒTbÙÈĆ$4ѦŽ$q#ÈAˆDâ'P’„Ü&áIÊNWRº—¸¦0¹› ØlCbtã§{;Ùö϶ƒÔ¢i HR]’ìž4ñ©IJJÆV2ÏÖ~»¥Ý0ᇠ¸eÃOxÜVâ¹AÊßvûÜ^ãˆBŠQCŠycË(ÉFLÞfóæŸ5&é7U*©X:ÁÖж€h@p£ƒô À#€40 €:Ð `€øÀXÀÀþ Xƒ´¡1 ˆUBªÀ¾”4¡Ð€Cú"Á pK‚€±EŠ/Ñ~ŒØfÃrì`?øȆDx#Á/É~P’„•Tª¥¤-!} èdƒ$|Óæø7ÁÔΦ{#Ù E(uCª7¸”d£&Í6j"Q¥(°•„® pký_ëXúЀ6°®p{§8ò×–¿ øp[‚Ü=áïxËÈöG²è—Då')DZ"ÓêŸUµ­­,és{›ßþÿá& 0R‚”¸`3Â{ƒÜ!Á 0I‚~ð¬…d.‘tŒ„d#\àæG2=ìdƒ$^"ñ) HNÒv”ܦå…,)u ¨bs™ðφÔ6¡ËNZx£Å¤ý(LBb,Qb‘”Œ¦ 0iñOŠ˜”Ä­ek-9iËÈ^CXŠÌfc5-©mÑn‹—\ºîçw=ýïð€¬+á_è§GÆ>2—”¼Ð¦…?)ùRš”Õ]ªí†l3m›lÞŠôXmÃhhÃFà§ ÀÌ`'A:â%(•¨(aC äW"ïxÉÆN6°Žts£ÛÙ8Eâ/ˆ”Dê'QM hXÀ—<¹æ0ùœÌæl“dœˆäG};é÷¸ƒ´¢}éH2[ÒÞÔî©-Ij¾UòÌ–dº¥Õ0•„¬¥e+IÚNÚÆÖ8ÙÆÎÂvÔÞ¦þ‡ôBˆôo£}&0Ì"aµ­(ÙR Wb»•´­Ö®µ‚<ãÃÃΧ58p3”  e(@Ú@`²3œÀv0!- hT Pº†p3Å(|à!Á ,Ib{Ø«…\.!q dc#RãG<¡å(DK"Y#‰MRj”t£¥h+AmKj`S™`ˬ5aÁuÓ®žè÷H@ÒøŽp¥%))³MšˆTB©H¬`«|[âý—ìÇ69³ÉžMwk»›üè—D¼]âïª}T ÈnEê/Rä°eƒ6Ù¶Ðvƒ´Ò¦•aëdk#\à·Ë¾^%±-–Œ´h÷G»ضý÷î!± †ø7Áo xK‚\€|4 «X$$D‚ {ØÀî@:Ì`€&0 Xƒ4 ëXB‚°•…4)¡q ˆf0ð߇¤="¨Ä†'!9 T‚׸ÃF4Q¢øoúÐþGòC¢ô¤Á& B U2©–|³åí/iŒ|iH› Ý@:æÏ6“ü¡i H¾EòIRJ˜äÇ'í?jhSB¶•´´õ§¯xìCb0™„ÔV¢·)¹NSr›¸À À^¼à¤ &Á6 @J8À‹X"AÐF‚xÀµ¨4 Àv,!a* PS˜¸T2¡¼ àyCÊ!ðG‚kX§8,ág `c:ÐÜÆæ:á׬}d*!QØKXØžÅ>)ñb‹]rë˜œÄæy3ɳMšrS’üïçÜ>âÐv‰äO$ IiKJuSª¤5!ªÍVbšÐŒDbpë†01M hFB20ƒÀÞð4  0a‚ä °€*AR PR‚Œ`¤ +\ ð_ƒ\àòCÂЖ…8)Áp €eC*°Ý‡ŒŒDaþðwCºà߈4A‰ H\‚äð¯…<)áA MBj°•„$! HBB@’°%8 ÀRB’à¯Ü.á’ l`è‡Ð>‚È€&‘4ŠTR¢Â¼…ä2A’ \jãhñˆ?ñÿì‡dy#É.IrOÒ~•¨E‰,It‹¤! Ø>ÁØÀoCz@Ò<1á| à[BÚð¯…P*L `QÂŽ@¢(áL `U‚¬0±…Ø.Á‹ XiHà|;âˆÄF$‘$‰ÄN"œà±ÅŽ/QzŒ˜dÃXÀãGÚÐpƒ„à×l3a h`p»…À.l `[Øð·…Ü.á‚ dC"0цè7AÓ˜|à ñˆÄF"U¨Ÿø*AR ¡ð€{Øà÷Ä>!ùÈ!1 ˆD‚:Д„¤&á7 4Q¢®p´…¤/| „d#KXÞð:Ôh{D qȆG²=’Ü–äô' ”Ħ$1!ˆÐF‚*PˆDB!шlCbèˆÄF"±ˆàGG8–„´'8 (QB¦0±EŠ.qsŒ0aƒ3˜×¸8qÃŽØvÃæ10DÒ&’¤½%é>Iò&á7 „L"W¸” $Ñ&‰4I¢P€•Ä®&0 ¸MÂ~ð¤…$*¡U XbáÀ21‘ ip€æ‡4Qò°}ƒö±H AR ¤…$?!ùH²Gr;’X’Ĺ%É7‰¼PbƒĦ%^*ñ HB"”„¤)!I ˆdCÒ‘,‰d]"éHâH¢E”„Ã&8ÉÆPbƒ°¥…U*©`KF’4‘ j#QàG’<’Ä”$¡)ÉNKÒ^“XšÄò'‘D S"™XªÅ}+éi‹LJòW’À–³%™.‰tLBbDš$â'= èP²…”¤…@*XJÂX"Á µÏ.y>IòO¢}üŸå(1DJ"Qâ¼¥åE*)VʶWb»L²e´-¡uË®_Âþ¨¥G*9S ˜URª•€¬p+`KYrË–¼µåÊ.QzKÒ`“˜¸ÅÅ”,¡f 0YÒΖœ´å³-™p‹„]b묽f0)ˆLBd ˆÌEê/Q|Kâ_¢ý$Á&0Á‹LZdC"t˦z3Ѧ4kÓ^˜üÇæG29”Œ¤f0ÈÎF…4)§Ù÷¸ø %(#AІ…„,!Á«EZ0ц’ô—Œ,[»wn%ĸ÷ÖZË_k홳2ö^Í™³=g¬€°vØsbÌy-5¦¶VÊà\ s¯à¾WʦTʱV+5f®ÕÚÂXK-e­E¨žSÊ€P C¨õ¥ÔºŸSêS«b®ÕÞÃY3&%D¨–ÒÚcLi­5§DèŸâ…Pª=G©•2©•5ƒ°vÎÙÞKÉ…pª)E(Å£”rR JIII)%¤´˜ÓmM©á<(U ¥T¬ðžzTÚ›_kí®µ×‚ða,$2Aèa "BŠ‘R1F(é$$„“bXK ™3'tî¢TJžSÐ*CXk#Œ‘’ê]N™ÓF(ÅH©æ¼Ú»WwnéÜ;‡”òžóÞ~OÊ@H-¡$$†Ò"DHµ£¤t’BZKI¹7(E§Tê¸W Yk/eìÅØ»:gMy¯8W ë]kÖzÐBÈY"ĆÒÒZN9ÇE(¥E¨µÞ»Ú«Tl‘¼7‡ã¢wáå<§°ö3æ~ÏÚ@h=¡Ä8‹b?GéU*¦ÔÚ¢B¤T‹ a®EÈÁØ;+emI©7–òèÍy¯áüBXK¢”2ÂXNÃD¨•D¨•Þ»˜ƒdŒ‘3¦¨ÕclpÈ98çC¨wáå<§Äø „PŠ&DÈõ¥t®¢’RJÍY­Uª¾WËcí£·àæœÓÆxÏÉùBA¢t~Ò¾WÍù¿D¨•D¨•⼂Ð] ¡0&@ÈÃ8i1¬5†ÄØ›cloMéÇ8çTêžSÊ~OÊAè¡$Dˆ˜“‚PJ‘R,…»—sbÌùŸ6–Òå£Àx¹÷AØ;"d}²ºWN ÁDèG¨äüŸ”¢”V Ág,åÜ»˜Cc a1æHÉs.h «5fìݜӚxû?hY #4f”ÒšuNªeL«å|¹W+aÌáœ6FÈ䃾wϱöAÈ9bl~ÒÂXN9ÇEè¹#€ÒZOIéO)刱ÒÚ\ q.%̹—’ò`Ì‘2&ˆÑsnsÎyé=("TJ‘Ò:jMJ=G«un·Öû a,Ñš6ÂãÜ{½w¯µöÁØ;â|2ÒZN‰ÑG(àïãÈyð@È"D’¢tSŠqT*…D¨•¢U ¡]+¥¤´—’òcLi¤4†ôÞ£´~OÊCHõ¦$Ä¢TJ±V+mm°f ÌÙ›`l=Ç»ç|ûß|!„1N)Èi .¥ÔîÃ+Eh·âü_ŒqŽ4FˆßãÄxb Gˆñ9'%X«bìf Á¼7‡ˆñ ¤ŒÑš]Kª%D«el¹#b¢7VêéÝ;Ú{P:D(…ã¼­•³>g‡PêƒPc ax/кÂøc a¬5‡`ì D¢\KŠB+Eh¼ƒ8g1Æ>‡Ñ"¤È™"¤] ¡—2æôÞžSʃPj7Fé1© ¯•òí]¬uŽ´æœà³vo™óA¨5â|…²î]Íi­)å<Øap. ¤ÂXGá"„pŽ`S at.†p΃~Â,E‰¡4+`Á#dlAèD0&D¨—RêfŒÑÁ8'¨õ!D(ÑúkMjeL¬…¾Ã(e i­8Çðô~¦Åè½%$¤°–.eˉq4æ˜FÀðPj 1 ̃pnðGáH)à¼ÃX{b8G 1F.…ÐÔƒÄx‘ LI‰T*…会@rAñ>(q$”’“²¥T«Qj0FÍ™³hmmͼ÷Ÿ $9‡1¾7ÊiM0f Ü›’¾W̹– ) Œ‚@Àø"@˜à\ Á¸Ca@(Àƒ‡âxO ‘r5F¨ódPŠrnVÊÙ0&¤Ô#¤Oê(E U*¨E¬Õšã\lQŠ4fŒÞ[ˬu…ðÁh-"d‚Ræ\ÍI©0æß›à´‚ D€Ð€H  $@¨@ˆÐZÐI !l-†ðÞ!Ä8 ð^ ¡´>‡Ñ#… RÊcLiµ6§|ï ¤ѺeLªMI¬5†½£&dÍa¬8·ïÝûô~ªFÁ%ä¼Î™Ó¦tÍ™³=g¨àT €à@H$€ÐÀ˜€ pn@\ Ì9ˆÁ)Å8ărR J AM)¥Ì¹™³6q!ï=èm ¤„Óº¦TËYk0vÎYËlmŽÐ=G©`L?‡ñÖ:ÊÙ[9'% ÂxPÊ@¨ € €€( $@è*@ì„àœ |‚XK !d4Fˆñ$L‰“‚pWJé„0†´Ös®€.EÉq.(µ®•Òë]lqŽ4öžàœ¶vÏ­õÂA⼑³bOÉùF(Å%¤ 8p€€P `ÀŒƒ0fB(Z AÄ8ˆ¡)E(Ãcˆq2I‰1J)EÀ¸ƒ0pN ë=h] ¤Dˆœ“’¡T+Eh°&Í£flÎiÍ<çà9‡1¾7ÊiM7¦õ¢Ïmí¿Wê@¨ €0ÀÀ0P*A0!`¬`„‚xO ‘r5Ƹ÷ä`Œ²vX ‡0æ¸×ƒ°€Ð/Eéq.(¥®UÊê]L 1¶6Í£Mi­™³8æœÓ´v9ç>‡Ñàƒ°âE8§"¤TÁ˜3vnÏ™óEh­1¦56¦©u.«ÕzÇXëyo/uîÃØ{(e  µ¶¶Ý£q®Ó¼‚öÞÛõ~°BB¸W¢4aŒ2bLK9g3æ|ëtƒÒ:GOéý\«€T €à€P, À$€Ì„@ˆ¸m ¢ A‰Á8-…°Ñ#¼wòLI‰T*…ä¼™ó>rAò>Hq#$d’RJ_KéÙ;(Õ©"¼W‹Qj.ÅØÁ#c¬Ù›4öžÚCp.mÍ»WjóÞ{é}0Aè=aÌTŠ‘¾7ȹ)¥4˜SvnÏ™óEh­2¦U:§VªÔfLÉ­5§àSªzQÿ?èQ "¤TVJɱ6(5¦ÔÚ²VK)e.%ľ—ÓbL­•´Fˆ×ZëvnÎAÈ:§TðÞÝ{¯áüA(% alH‰Ž1Çèý&d̵–³FhÎÉÙB(E$¤• Uʹ^kÈ P  $À˜€°VAÈK ax/0æ"DH à\ !¤;Gi !d¨•˜[Ëy0&PÊsNnÍÙÏ9çŒñŸƒðƒPj"DHá$䜙"{OjII*•R°V Ø[ Áx0†ÈY :gMI©6ÆØá\+ŸsîáÜ='¤ûd€Ð†øw¢´qŽ26FʉQ1&$ß›óî}Ñz/LéO©õ²¶X‹im)l-…ø¿ hͶ6Ç$äã¼|’@èm £b‘Ò:]K©Í9¨¥¨U ¸W =g®uο×ûbìÁ˜4†Ø›{onQÊ:ç\ñÞ;á|/íýÁX+ !„K‰qš3H'$丗NiÎùßBè]'¤õ¡Õú¿_+嘳ÒÚ€Pà|‚0F P5¡ !…PªCHâTJбV0ØÄxÂJIIH)d¬–¢Ô^ËÙ1¦|Ï›#dqN)Ù;'´ö …²+Ei %d¬›b‚PJaL+`±Ö:Þ[ËÙ{0æÉ™3?gí]«·ââœS¤tŽõÞ½g¬ü„ P–Ãø¢Ôu޲BHJÉY1æ<ãœsúQº7M©µSªu¾·Ø»j-Eĸ„䜔‚V Áh-优³g á¯5çàSªzAü?ˆA"TJŽQÊOIé•2§´ö¤TЍU ý_­e¬»—s`Ìy3flÓšsglîÀ9§4ìÝ›Ìy™ó@ Ô5†±>'ƨÕ!d, ”ò^My¯<ç¡ôª•TjX«¯önÍÛ‹qu. 2@¸à\ Aˆ7á … ƒwâ$Ä„0†B(GHé&$ÄÀ˜²vQŠ1S*e€°âÜ_ á‹1flÍš³Vo áÍ9§€ð#ä"Bè­£ô~”ÒšhM õ>©%$ªB¾WËUj®ÅØÀ˜cLÉ™4–’Ø[ zoNIÉ:·Vñ#Ý{¯ÙûA! ¡TDˆ‘z/Gˆñ$¤”­•³"dNIÉ?çý£tÞ›Õ:§[«uбVžÓÜ;‡wîýü¿˜g ã\k”²W áP*@¨BÈa !¸7ðþ%D¨¯ã8gñÞAÈ9"ddŒ’@IÉ9/%ä䜔"„SJiY+%”²—"ä` Ž1ÆtΚÓZoMéÎ9Ç€ðâ"BÈ©#Ôz”RŠeL©é=(õ©"ºWKAh.uο—ób¬±–46†ÖÚÛsnn1Æ:GHï]ëÖzϽ÷Àˆ¡<‡‘V*Æøß"¤T¤”’þ_Í©µ=§µ¢4¶–ÔŠ‘Y+%€°rÎ[‹qun­ñ¾8;b¬U‘ò>d̃˜sðBÈY#D|’2FIÉ9,%„Ì™“¢tPŠK)eTª–ÀZËYx/™#$hM °6üß xO ò>H!d,ŠQJgÍY«6ÖÚá\+s®ÙÛ<÷žúD€0n ÃHi¢tgŒò@ÉÉ9-¥´Ñš3¶vЊHé?§õn­×jíd¬•®µ×*å^{Ï€ðÃøóeœ³³¶“Òa¬5† ÔCht‚@ñ(żƒ,e±¶;`þÄH‰‚PL‰‘4&„Ø›¢tOÉùE(¥0¦B¨WŠñh-̹—âübÌY˜3”Ò›ChpŽÒ:GŒñŸ3æP*B襣Äx“ÒzbLIÙ;(¥§Ôú´V‹%d®À½—³ aŒ‘³–rÔZ‹hmÀ9‡0ìƒÉy/…ð¿§õ ¤-…±#ÆÁ£Ô”’‚Ü[Œ1†4Fˆá#Äx2Eˆ±)%$ì”"„Q !H)0¦¢V Á_+圳—â^ËÙ†0ÆDÈ™ãÈ¡„0Š‘Rh !"ˆQ 1F) !%4¦™S*wNê)E)Õ:¬UŠÅX«el®åÜ0Ç㬕’ÅX«elŒ‚1†0̃Hi ¡´8GêCÔzCˆq#d¤”“rnQŠ1T*…ˆ±òÞ^‹Ñ„0†0ÆC(g á£4f¬Õ›ChoMéÆ8Ç@èøyÏ9ó>h ä‡â+Ehé$¤”–’ÒkMiõ>¨å¨U ³Vc`l Ѻ9 ìƒÐzáüBHI"¤„’ò^O áJ)E`¬rÎ] ¡€0,Å™C(gLé¥4¦´Ö›SjoñÇ8ç@裴y!ð>ìý „…Pª#DhŤ€“Òz_Ké½7¨¤TФTƒ¼wqî?Çù!H‰Â8JII5&¥¡ WŠñk-eà¼S dL‰›3f”Òšã\m±¿7ç ä¢vŽÑãjÍY·6ç áœãœvÁãŠQJ4Fˆý¤´–•ÒºdL‰É9(£”rœS…优CcÌy›3fœÓ›3foÍùË9gXëÂzÏYö>È ¤…¢CÈ¥£4f‘òII)U*¦À›SjzOJ!D)U*cŒq™3&Ò`nÍÙÇ8çLéã¼zQô>‡üÿ ”…¢CÈ¡#$dQêHI M)¥ä¼š“RvNÊ A© §”ñ£4f¸×“rq!Ð:pîsÎ|‘þ?È!!4&‡Pê(EÉ#Äx‘Ò:RJIu.¦„Т€P 1F)•2©Õ9Ã8g8瓲yO)ð>ðþ t„’C¨£$dâGHéE(¥Ä¸™Ó:rNIù?(¥¥”²£TjÁX“²xÏï=çèý T „‚Ch™#bâGHéE(¥Ä¸™Ó:qN)õ>¨…¥¢ T ±V+¥t{qù?( ô†Ò&DÈÁ#´v‘’2QJ)q.&dÌœSŠ|OŠC©5&§ÔúªUJÝ[¬5†"Aèi "TJŒ‚;Gi#%¢—âfLÉÅ8§Äø¡Ô:’RJyO*•R­UªÁX+9g!¤4‰Q*0Fí¤dŒ”‚[Ki™3'âŸâ‡PêII)Õ:ªUJ´V‹`,ضÂ1F(í¤dŒ”RŠ\K‰3§âŸâ‡PêII)Õ:ªUJ´VŠý_¬µ–µÖºã\i#¥$¤—RêgLéÉ9'Ôú¢B“RjyO*•R­¢¿Wë-e­e¬¸—î]Éy/&”ҜӚ~OÊ%D©E(§ÔúªUJÕZ¬€²ÖZÖZˉq.ÕÚ¾WÊuNª@(µ¥Tª T ­U«el°V ÌY‹]k®%Ä»—rù_,‚¨Õ¥Ôº¢TJ±V+un°–ÍY«al.5Æ»×zú_L‚±"©"¯Uêå\¬Eˆ³ÖzÙ[+•r¯à¾×Û`ìI‰1Ö:±Ö:ÑZ+qn.uμ—’ý_¬!„16&ÇØû*eLÕš­õ¾ºWJô^‹ý°¦ÅX« d ±–3vnК`L5†±†0ÈÙ.eÌ圴FˆÔƒ&dÌŘ³¶vÑš3RjMu®³ö~ÒZKUj­}¯¶¶ÖÝ›³clm¹·7–òá#}o®!Ä9'$圳¡t.í݈ˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆ€¾£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú> –%¾£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>¡6M€Å€èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èúf ¢¨>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú=ïxF€Žã@Sèú>£¶í½ï{èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£Àà{*Ê€èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú)JP$I>£Ôõ>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>¡Ìs¸nà{èú>£èú<èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>¡šf´#èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£Žãº.‹èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú<¬ë3LÓ¬ë(ª*D‘%‰ahZ£èdð<çúä¹>£èú=ORX–Dêz­«iÂp²¬ª&‰ž€‚ ‹BÐBŠ¢Žc˜…@PŒ#)ê{HÒ€–%ƒÀðað< b[èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£Þ÷¹Žc à ˆ!dA<¡hP È (Š€Z†A< È€ (‚ €¶í­ BX–!(I¸nÇ1TU BÐa@@P>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£4Í'Ü7 È( àx@P€  (F@PP (çø2 €€  (¾/…¡hn@P € (( @P € €2 € (>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú+ÊñhZ ( (@P@ (ˆ"2 €x@PŠ¢“dØa (Â02 …@ àx€àx €@P ¾£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú+*È2 àx…@€ @<€<àxx(  ("H‚€ @PŠ¢ä8 È (dØx ¾£èú>£èú>£èú>£èú>£èú>£èú>£èú3ìú&‰àx € È „a( 2 …@„á'iÙ†aàx €( àx@P>£èú>£èú>£èú>£èú>£èú>£èúÇ0xA €(  (@P €@P (RÔ¨ª*N“Ÿçø¾/€ ( €P (èú>£èú>£èú>£èú3ìú‡ #H<àx€F€ (P ( È0Œ"@P’İÜ7Àð ( €ãèú>£èú>£èú>£\×%È€  D €@PZ€ (( ˜æà € €@P (ª*€€ @P @Sèú>£èú>¢N“ƒ ÈA@P ( µ-I|_ bX € € € ( ( (¾/Žc˜ € ( ( € ( €@P€  ( ( € ƒ È@PF€ ( €Z…¡hÀð€¡@P € ( #Hø¾àx ( ( €F€ )Fàx@P( € € (( àx2 € €< ( ( (.ȯ«WÕ«µÎÚë¡uдöZ{-|Ö¾kr¹ Ã-a–±ûXý¬Øl ¹e\²²}Y>­ùVü«åUò«e‹2˜½L^§.S—*•ÊŸµOÚ¯)W”­ÜVî(.T*% ’‹E€¤BR!)€ÔÀj€õ@z©aT°›M¦õÓzéÎäçryM<¦ P (‡CŠF#›±MØ©§TÓ¿XŸ¬P˜JX,–íKv¦“Iž´ÏZo™7Ìž9O¨1”Ê9•ÊšiM4©ÄTâ=BÞ¡o~'¿êÉõdýq~¸¤ d†²H $“œIÎ%d² }¾ŠiÅ4âBN¡(T ª:µZœaN0ª«UUºý~ŽðçxsÈaä0õ z…½ýÞþï¬×Ökö9ûŠ”EJ"é‘tÈÑ$h’;Ýî‘@H $ôÒzikĵâgy3¼DN¢(6 I$‚¡©PÔ¬VV+,V ­°öØ{za½0âq9YܬEïÉ×äïwŠ<ŠÞEoR·©[àMð&úó}y¡Pˆ¨R)© Ôˆ9D¢šQM(ФhR?¹Ü“0I˜%ª’ÕI¦Ó y <„¢;Q©•ÔÊê¨TºÅ]b²ìYv-ÆÖãkµÚ‚ýù~üÃaαéXô¬º6]>IŸ$Óhi´5ËZå­­ÆÖãyÕ¼êáõpú¹Yœ¬ÎŒ7F¯ý×þï0w˜<“žIÏU‡ªÃá5ðš}ä>òÏÎçú#ýˆƒjAµ!}P¾¨dG²0årØGì$éÒtézÔ½joa7° P ©ÔŽêÅFâµZŒ±µXÚ­…‹¦õÓzû }„Âüa~1ʘåL´fZ3=žŒÓ3i™µÂÚám¬–ÖKyͼæâq9^œ¯N÷Fû°ÁØ`ïdw²<¡ÞPïYg¬±ÝÌîæwÌ;æ*G£ÑðÈød~À?` l6HP´(Z"ÉdŒ­FV¤5’ÉSd©²fy3<ž.O(µ”ZÊvµ;Z°9X°¬XV-MÖ¦ëœÎøµ|Z‰aD±´Ú °FX#ÔŸjKÒ%é5‰Äo7‰xŒ¼Fÿ#’6I$½^?4ŸšTy*<–u‹:Åù’üÉ–àËpl6 œžŽOGÈ þÿ…÷Bû£ÑŠi)t”ºbå1rž½O^©$T’*£ÅQâ¿_Œµ!Z®•—JËõÅúãÕˆjÈìdv3_Y¯­†CX¹¬\ÚPm(7’›ÉN"·[—¥ËÒéŠtÅ;C¡…RŽ)0¸˜\G@# Ôjb°û}È>Íf Èd-r¹´ZKv%»=J¥o2·™u˜ºÌd 2²ÍYg£QáÈðäJ?¥!{½ˆÈ$dK­%Ö™1L˜§ÒÓéjS%)’«õUú°‰XD­|V¾+²ÅÙcõ€zÅ b2uÙ:ìæös{KA¥ ×kŒ6Îg ó†ùÃŒ]Æ.æÓsiºœNÊÇea&P“(Cª!Õ¦‡ÓCªÕßøoü6æs á†ðÜÎõ”zÊB,!úHý$ãbq±Sx©¼[ç-󘿌_Æ£QÅ€âÀxq<8ŸÞïe2Š45“–IË&}>Še2˜™LL«ðUø,aÖ0ëo%·’ðÝxnÁI`¤±‹XŬ®W=åžòÓâiñ6 ›ÍÄ6â€ýÀ~är 9ô\ú.¶—[K´¥ÚRê$u:û}„b 0ì4v5Îç u:‚÷±{ؼ8^0˜L €ŒQÆ(úh}4E!"“I‡¥9œálL¶&b¤1RŒ F³ŒÙãèñô€@¡Êåß„oÂRu):›M„(Q”(Êtå:r´Z@²¸Y\. W+Ö¥ëS å„òÇ^c¯3Y‚- ¶„ÛTªÙGl£·X[¬.g ³”­ÊVèÝtnº«UŽÇ7c›¬áÖpìûv}Ž8‡C$‘’H³DY¢(çs‰ÃDá¢ya<°©°TØ/KF¥£À1à ð†øK;%”Ê e°âØq‹ØÅìjÊ5ešNM'ŸÏ‚ívˆ]D.£ÏÑçé^ä¯rq8Æ¢¦QS*)•ÊçµsÚÐ}h>¹Š\Å/²—ÙL=&“"©‘TÍaf°´yŸ¡+Еè½T^ªJù%|™sL¹§ùÓüêa¥0Ò°]X.±ÞXï-ÛÖíëÌ¥æSµƒÚÆäcr2ìYv-&‚“S©ˆÙl‡·M[¦®W «”eÊ2èÔtj;]Ž.ãWq«´]Ú.îÙwlŠ[Å-âQ(`00;ƒ˜AÌ!P‹(a0Ž ³YŠi4ƒ,–@ðx E'"““… Â…n· ~¿gã3ñœŽG¿þ<ÿ†ïCw£†‘ÃIO„§Ânu7:¡þPÿ* U*áõpúÏQg¨¹U\ª¯§WÓ¬;V«"‘FÍ_f¯´zš=Me6²›jYµ,Þ°oX8ªUgw3»¨©ÔTíÃvá»àðNæ·s[À™àL#Uƒ*ÀÿÀàÄâR©½ÁÞᄠ‡tCº+ÇF£è!ôD¢På(r–lK6&$ãqª˜ÕLrÏ9gž¨TH#D¢&I$ŸHO¥Ü’îIßäïò‘IH¤ªjU5,–K^…¯Bímv¶À•`J±g˜³Ì§&S“Ôj¼ÈÞdòÒyi]”®Ê_†/ÃâLñ&ö{ Ü0î~€?@!o·È”äJr3=ž7H¤år‰nd·2hµ4Z`N°("”J9Åâš¡MP©¦TÓ+'“Š÷Õ{êÉdŒµZ„-õ–ú˨ÅÔbôz@¿²_Ù0’I Lv&;¹Ž\ÉdÈ2ûY}¬ã¦qÓAù üÒ§iSµ6š›Moæ·ód‘²HÛAm ·S©ô†úC„ýÂ~ã0q˜9Gœ£Îo×7ë£QѨê£uQ»ÝnâÇqc¿½ßÞñ¢xÑ<Ô^j/Ow§»ÚEí"ø/|¾p8 $’µÚ‡þCÿ"ÜQn(îtw:I$€•JΦ7S©Á¤àÒ|ñ>x¢UQ*©\T®*†•CJ­VήMW&¬G#‹>eŸ2Ú¡mP¹[\­¯W€+é%ô“e‚2Ãaα„ ‡VC«+Y•¬Í,f–3Þ™ïMƒO=§žÕùjü¶ Ûm¤6ÒqY¸¬ÞXo,8 $W+½È^æs¹úý›×Më®× íQv¨»Ãá ‡†CÉáäðôz½q^¸¯u׺ëãÉñäúƒ}AŒk5‚ÌÑfh¦TS*(@ŠmE6¢Ï‘gÈǤcÒ8 ¼Þe22™8œUË*å—g‹³ÆV3+´@Ú t¦:SÏ çÀ“àIþ„ÿBƒ:A!®×H£„QÂ6‘H‘H‡¥Ò‹é{½Šk‘5ÈžO(K%ŠCu!ºœÉNdª*U+DÕ¢jþårÊýe~µ†ZÃ. W«­UÖªõÁzà¿û_ý°ŸØOìO†'ÃiŽ´ÉºdÝ3Y‚¬æfs3B¹¡\Òâiq5BZ¡-s&¹“e5²šÛTmª7WÛ«íõöúû…Y¬ãDq¢9JÜ¥npg83£…ÑÂê­uV»ŽNâ÷q{¿½ßÞñ¨xÔ<ÔÞjoO§§ÓÚEí"ø+|¾oŸ7Ï´·Ú[óEù¢sž9ÏÔÎêg¯3×™ú@ý ‚A !g³ˆôHz2 éGô¤Ðh h´ fÝ3nœáNp§ÿSÿª0E"˜!L¨ýT~ªû•}Êìuv:Æ9c´UZ*­Âá ›UͪñQx¨¾ç_s°YX,¬>V+-Œ–È´dZ2Äb Ök>}Ÿ>ÑÜhî5‚ c¦±Óaa°°Úom7·[­ç&ó“½ÀÞâ^q/9‰Žc'1“ Ð éÓtéºçsŽÕçjó¼iÞ4ðÐxh< žPOBÇ¡c×9ëœ÷e{²¾>_/¨gÔ3ðUø*ýš~Í šFÍ#-!–Ãxa¼0ÇcŒ£ÆQã`!°ëuŠ@ HÁHà¤ßro¹Tتl\˜.LÌ€æ¶ã[q¼lÞ6rÈ9d›͇ ÓÐiöxû<@¡&“H€”@J-ñøŽÓGi¤ŠÒEiW«Šb•1J›ÀMà'¶SÛ*Åb“½IÞ§ÝSYŠÚem2Áå`ò³c P (;”Ê¥RŠ…EB£xѼi$‰’Q™(Ì—™K̦®ÓWiÝtAÆ£ÜQî)µÚŠ›õMú²Y@¯pW¸,Œ–FKN¥§RÞio4ºB]!/4—šKõú‹]ƒ®ÄJb%1­ÖŒ‘H‹-–ÎÍ­fÖ³ûý"V‘+QU¨ªÖuk:¶#[­ªÕ r¹NÞ¢oQ8&œN(çs‘ÅÈâæLs&: Ž P¯ ׄí~v¿;Ì]æ/—‡KÊQå(ôMz&½yÞ¼ïw÷»ûä5òú™}L¿„Ú—íKüþG˜€L÷‡ûÃÀ±àXæs8‡CŽI$ƒ´ÁÚ`ûH}¤Cw!»’<ÉdñRx©V€«@\s.9˜ÝŒnÆo#7‘ªÕ n7œcN1§QC¨¡âLñ&|> àÏðh/d²E ¢‰³DÙ£=ÑžéT‚*MÝ&î–«KU¦t: ÎDç"•?Ê¢âQq)w”»ÊŒ%F®aW0®lW6,MV&«?UŸªÚ‘mH¹B\¡.ö×{kåµòÛ}¾ÃUaª±qX¸¬¦@Ó)½”ÞÌÁf`³ÀÙàmFŠ#MŦâÕ–jË5êZõ-›ÖÍëo ·†ÝÅnâ·ðø ‹Ž}Ç>åzr½9Õ\ê®’·I[«ÍÕæì»v]»]ίG#Ç9ãœózy½=L^¦/l7¶áUðªùß|ï¾ÛŸmÏÏ'ç“ùÍüæÿëõÀX`,%02˜X¤¬RYe,²—,K–&ãq´ÆÚfç3sš“MI¦Ü“nIÄÐâht§:SžO§·³ÛÙûŒýÆ‚EA"¡gP³¨ŽÔGj0ápmG¶¤ªÒUi\Ô®jc¡1ЛýMþ§ÁÓàê E"“ÙIì§ÖSë*«•UÊØEl"Á `†²ýY~­l¶ …5šëÍuæ½s^¹¯ýþŒ&f3Q‰¨Ç5cš²c™1̽Ö^ë8œFÐ^h/4£ZQ­K¥ƒ[E­¢Øãlq¶»›]ÍÏç‹{•½ÊàÝpn¸±ÜXîJ·%[š ÍèZt-:Š]E.¾ç_s¶½Û^ïgw³¼CÞ!ï+Ç•ãÑ¥èÒö {=ç^ó¯“GÉ£êíõvüA~ ¿p߸oô'úâq%Àä`r$R’)I „Ž@« UÈ dâ ñ”‡ÊGr#¹üI~$èrt9DÀ¢`T*½ÊÞå rÐ9t°ºX`a00˜êÌufp8©XÔ¬m«6ÕœBÎ!gFC£!ÞÜïn{=‰›ÏÍèd ²! ˆGD#¢ã‘qÈëÄuâG½#Þ• J…¦ S)³ÙŠxÅR+íöŽ*G$R) Fd£2]Å.âšzM='\Ó®j‚QF¨¦0S*A н•^ʺa]0±LX¦,ÿ–ËiÅ´âäÍrf»¾]ß/ׯì Ök q†8ŃbÁ±öû ¢ÆQc1µ˜ÚΫgU´9Z­0Ö˜kTµªZN*'ÅÉbäbH1 X,H`$0u :„¯’WÉ1´˜ÚN 'þIÿ% B!Q(¨”V·+[–RË)e¿òßù{,½–aµ0Ú™,Ì–f|#>«XÕ¬mû6ýœHN$'DC¢!Þïz¦=Sxϼh”J‚‡cC±¢£‘QÈÚ”mJBé!t“ÓI饵Ú‰´ÎÚs-9–Ÿ·OÛ¨§SŠWµ+Ú¡PŒ«U«uUº«µ„ZÌáfpµÓZé®— K¯׊õ½zÞ¿æ_ó0”ØJlK%‹-ŽÉ[d­²é™tÄÐh 7Ø›ìO'”'Êå#‘áP¨HV"+Ë å«òÕùuˆºÄ_ý/þ˜­ÌVæXƒ,A¡¼ÐÞkc5±›˜ÍÌgc‹1Ñüèþw;Æž¬ÏVg܃îB‘È„B!ÇÐãè¢ÔQj51˜MH&¤×k‰eT²ªeM2¦œ:N'É“äÊ e2“MI¦§¢SÑ*šUM*ÒUi*¿E_¢²yY<­E¢‹z•½JèÕtj¼®^W/È—äL ƒчèSÊ)åYÊ,äÿb±>hŸ4PO('”A … B!M ¦T´*ZšŠÍEƒrÁ¹i´€\m.6—·‹ÛÆà a„ÇÂf3?šRM)&Á#`‘»ÈÝäqá8ð5Κç}S¾©ëHõ¤}Ú>í 8H?ŠÙ ì‰ÿDÿ£@‘ Hÿ”ÊKñ%ø•ëJõ¦6Ói¼tÞ:zq=8¡uPº©”ˆÊpõ8z§SެV?«ËÕåëEŽ¢Ñ•hʶö[{.`0 ¿õßúùÉ|äS¯)וЇÅPâ¨qXX¬,Wh+´2‹E§‚ÓÁq¸Ž^J/%Ì æ-#‘”¼Ê^g¸3ÜÍGæÏcg±¾Èßdr‰9DUΪ烃ÁÁì”öJ~?  AÐ è?´Ú© Ô‰èDô#4ÑšhüÄ~bJÉ%d•£JѦS©¶DÛ"xÍ­V’ŒIF%Y¬‰ƒôÁúlA6 ÛNí¨'Ôê6e2˜uL:¨ÉTdªÜÕnjáõpúÂÙal³DY¢-qÖ¸åªâÕqk˜µÌ[]-®—Ë‚eвèYxˆ¼D_j/µ7ŒÆ'Ãá‘\È®fE3"š F¨ÃTa³dÙ²o-7–œk5‡BáaÛXí¬yo<·Ÿ …Çíóöú½^„oB7¡ÎÐçh¡P‚3…¶GÛ$ RP)TTª*`Y0,šÓMi§gÓ³ê¥ÒŒ5F¥½RÞª• J°ÅXb¶¡[P°8X,²VY%ëBõ¡|ܾn`0˜;ŒÆ!“ÉpƸdà2pœLÎ&ƒ“Aɨ´ÔZl16›˜ÌG #„‘Ë”åÊuE:¢ðø¤“ÒIóùÈ?¿ ŒPF(M¤&ÒA ŠLE&#C‘¡Èý~‚JI%$•EJ¢¦ «ÔÕêuÁ:à &P(´”ZJW+Š MP&ª³UY«S©Šý~ŠÉad°c 1„˜õ z†M&‰—¼ËÞgB3¡-M¦¥CR¡°\Ø.mø6üüÍþg!S©Ðüè~v;@ž4G´£ÚQöäûr€G@# ´ZHV´+Z 1ЬEV#W‘«É$€Jé%t•_J¯¦Ói«´ÕÚue:² P(¨”TJTU**ŸiO´ªjU5+=Õžêø|žlÏ6h4Nšo7ƱsX¹²Ùn)7›öMû's¹Î˜çLu´:ÚöŽûG¡ƒÐÁñ|ø¾~¼?^ I$ˆ9”Êu :ˆœDN"ÍfˆÛômúAe ²’õIz¥d’²I‚„ÁBk55š^N¯(”J(år”‰JD§®S×*ŒÕFjËue¹±pظm†6õÚÇ3‚™Çtãºs¡9ÐWŽ«Çucº±å0ò˜{l=¶f³Gý³þÚm6„„BB!¸Ü•J‚/E¢ŽFG#$3R©5$š’W+À˜dL2&¼Ó^iØ$ì€5@¢—QK©D”¢Jy<ЍYT,¬‘VHœN'SŠ)Ê,åt:dβgtsº9ä òzè=t8œï÷ŠI$ƒ=Až¡a°È|„>B(•JŒF?£¹QÜ©4ŠšO)'”–@K &/S©³ÙŠvÙ;l .P(ª”UJR%)žeO2ªU«•GNÓ§iØøì|w¨;ÔNÏ'g­ÃÖáòŒùF~q?8  ˆ&¤R †žCO"3Q¨±$X’5A ¤GÒ$~Ò?iE´¢ÚZÕ-j™(L”&ã“qÉßÄïâ•@Ê¢ÚQm)OT§ªzÅ=b¨%Tx‡G$‰+ä•òT*—XK¬&iS4©¿´ßÚya<° ³PY¨ÆTc*WE+¢Ÿ5Ošª(UÏ‚çÖëû4ýš€Q@( z=H9D¢• ʇ8Cœ"JQ%(²Y 4­VEG¢¤YR,©9dœ²W +„˜ L¦‘“HÉÈ´äZ{A= ¡P‹(Ù”lÊ[u-º PªXU, 8H$´Z€…]B®¡ÁP਋´EÚ*E"ŒsF9£˜ÑÌi´‚ÚIÅ$â”yJ<¥©Ô‰ŒtÆ:kå5ò.N—'×ëŠ% ’QG¨¦S *U ª©…TÂa°…®B×!ÌÐæh‹¤EÒ)i´ŒF£vÑ»hû}ŠFM#&“ˆIÄ%`R°)xä¼rf3F›¼MÞ'u“ºÊ5ˆqD8¤TR*)ž”ÏJеEZ«¥UÒ‡¹CÜ¢CÑ!訔TJ01¥FÒ£ÕÑêéôˆzK}%¾”ºJ]%¨’ÔI‰Ä‚jI5$œ“NI§¦“ÓJ Uª‹Eˆ¤âRq)ÁàŠ’5I­ V†‹ E…#ÑŒèÜänr=Q¨áHp¤¢Q D4¢Wý+þ—ÔKê&j5 ¹„ÜÂv ;Ÿ}O¾¨^/ 7õú–=K§˜SÌ*jU5*¼^9A ¨GÔ$EÒ"é(Ä”bPq(8•±JإْìÉ‘tȺke5²œªNU' ÓÐj•J‰]D®¤MR&©TÈ*„B © T„¬JV%$c’1É-t–ºQ (†•°JØ%ÎRç)$Æ’i±4ØœN'tÓºiú4ý…µBÚ£MQ¦©KT¥ªpÕ8j£õQúªîUw+9Uœ©KT¥ªX,—[K­¦3‰¤4ÒoY7¬iN´§ÄÓâj •JŠ E¤KR%©…TªE?¢§)S”«ªUÕ+d•²I}$¾’dm26šjM5&õz‰Ôäêr{M=¦ fP3(~Ô?j:•J•YJ¬§S‡ª7UªªEU"±áXð®HW$&¹\‰ÁäàòuÝ:îžÑOh¨ µ Ú F„¤ÞRo)”ÎÊ‚…AB§=Sž«“UÉ«UªŠñex²w•;ÊŸ!O¨” Je2Œ¡FP¤¢RQ)†ÔÃjzµ=Z¥ R†ªãUq«#U‘ªã…q¿ñ_ø ÔPj(…BŠ55š’­IV¦S)ÛÔíêGŠ©µTÚ¬V+f•³Jó5yšÃ…a¤ñRx©ŒÔÆjw¥;Ò£aQ°ª5Uªë•uÊÒÕijº­]V°:‡ÇQB"D˜H“ ³"vdSЊzbR,JEÒº@Ÿ]“ë²›€Sp äI\‰-`¬¼h— aƒŒ•¹’·3Õfz¬ÔÿšŸói2m&Mô¾ƒ8û`è<“± v$Aà(<æGœÈöçÜãçâ|üOÍ1ù¦?á'ü% @䎂1Ði: 'B'hDí Œ!Q„1’†2Páê=Cïh}íF"(ÄJî‰]ÑAâ(Â`ûvnÃù²6PbL@í¨µ Ãd!N„)ЦZËChbÍ4¡Æ”?ƇøÑÚ#DÄ蘉"‘$W¸Š÷sR.jFHÉœ#3„jþ_Éma-¬'ÜDûˆ§í”ý²ÀÌX‹ƒipm/ùEÿ(Ç.åÃ7îfýÍF¹¨×6œ&Ó„àã”Âr˜NŸ™Óó;š§sTòƒžPsÙ@{(!ó¤?EGè© t ¢tPWê ýAü(?… .¡EÔ1.†%ÐäzDh€í×¢:ôMÚ‰»QOò)þEœˆ³‘΢ùÔdVŒŠÑ¤ê4FÝèÛ½£‘ôvhŽÍ ­i5­)e ,¬õ•ž²ÖXZË Þ9{Ç1pF.Í-™¥³Pdj ¨‘µ8Ghåî½Ã«øuúßB<úçŸ\÷áü#î}Àíyý¯@|H‰Ì ™„¾ƒ·Ðž¢ÔC aM!ɤA<ˆ'‘"z$OD÷žáx"¯\‹Ñ†â0ÜFrÎA#aäq Ž!QÖ2:ÆGž(óÅ€#ðV~JÏÉ÷>â*JEIH²”–R’îj]ÍLBшZ3 æa\Ó¨šujDmHŽ Áá9¯§5ô샃Äx€OWÉêù>cgÌlýWªä€`P>ÚÛA·ˆ6ñ Œ¡1”0&†Ðå‚°Dhƒ­t"N„QŠ#‘_ê+ýEçh¼í##ÄjBѽú7¿GG¨èõI£É4}’²RJ@éH]  ›óbhšMJL I+Áåx<¸ã—s a ̰–4Éæ™<ÚŸSã…ÒpºN{aÏl;XkòƒžPsܺ{—O·aöì?ÔÇú™å \´`ƒ ‘Â8Bóh^mR¡ÊTBzˆOQ,%‚E/H¥é"ÒaŒ"‘º3·FÖHÚɸ£—x4‘ô>‚HiM!¤04Š‘CR7ÚFûI)#d}s®r"ZDKI?¹'÷'ÜäûœªÈYÖºZ×L‘€2fÆLØÒšRj¾mWÎ ¹Ä:.EÀîÅØ£Ðøz‘Éò9?d'ì…‰ 1$Ђš‡úÿBàÈ\B¡ÈTCˆcÑ1º&7ENH©É/¢åôcþŒѪÂ5XGHáé­#µ¤|(…b@¬Ha) %"¥$T¤ŽÒ‘ÚRJêI]Ii‰-1&‡$ÐáÒÊ:YH¡ô#-de¬™*%B–|RÏ‹‘cr/NeéÌÇî˜ýÓGhâ«yµo8°çéë=sÁ¦x4Ïaéì=>ÓGÚhÿçŸüô$‚|"„BÉhY-)¡Å4CÚˆ{Q7&âEpˆ®Ù¢û4g6ŒæÑ¹Š71GNhéÍÅ#ؤ€´’òBþH¯ií#æ$|Ä“ú’R_ÚKûI¼‰7‘'Û¤ût¢Ò”ZR˜ZS ¯cUìvøŽß(B y#O'Úäû\¬õ•ž²çV\êÌ^!‹Ä44憜ڷ›VóŽFqÈε‘Ö²»G×i— ä<‚ÇžúßCthn8¢'QHŠ)pb. FbèÌ]¾£wÔw8Žçúj?MHUi ­"á$\$‘:’'RYÚK;Iµ©6µ'ô¤þ”¤”€ÒŸâSüJº©WU+É%y$²P–JÕÊZ¹K„‰p‘.ĥؑ!J$)E/ ¥ôÝû mw ®áô„>ˆßií'ÍÄù¸¯üÿ‚ÿR_êL⡜T6®¦ÕÔ宜µÓ¼wƒp©î?~GïÉß {ô$„€P×¢ôDWÈŠùÖ"šÄ_ˆ‹ñ¨â5G@è(#å„zR.šEÓI" $A%ý¤¿´v“®Ò‰:Q'JoÉMù*Æ¥XÔ¯•áÒË*YeKbél]._%Ëä¼r—ŽRýr_®L i„ 1#¦$tËÄ™x„VøŠßN‚‰Ð_@ è½Â7¸H‰Q%Hd© ¨Æ•Òí,]¥ŒÃ9˜g6­FÕ¨çâ#ÆxÀÏ£yôo@aˆ 1´ ö„4†ƒQ*#E[H«iÙ#$o2æQçZ<ëH/©õ"á$\$“’af’LÒIý)?¥)T%*„ªj•MR»âW|K4éf-Ê¥¹TºÐ—Zø¢_L ‚Á1&"dÇ ˜ä&zdÏLÂi˜M3˜¦sМš“F’hÒMXÉ«5¢&´AÐ Úîèݹb÷,r ŽA2ìC݉ë‘=r-A¨ É[™+sjDmHŽÑã=&'¤ÄþÂäš‚óPÄêDiˆ12¢ÆTh>ÑÕ‚:°HÉÙ"Ã$Xd“Â’xRn¢MÔJ)ÉE9*=¥G´®~•ÏÒÎjYÍK„‰p‘/¥ã4ÀX˜ zaïLsiŽm2…¦P´Ìö™žÓ>ZgËM!é¤=5&£$ÖžšÓÓb’lRMª‰µQ6ã¦ÜtÜt›Ž“…êp½N$ÉĘ<àœ.®%ÕÅæ ¼Ôm#­¤i "¯¢UôLTÙŠ›6œ&Ó„ëflÓâ¦|TÐ0ÂBÊ(YEÄ¢8”\œ‹“‘¹7 GÓ¨úu"{¤Ot”¾’—ÒwŠNñJbÉLY+M¥i´³š–sRåj\­Kä©|•0¾&Äǘà+JeiLä œ4P¦ŠÔ8š‡[k`M”‰²‘6Û¦Ûtݨ›µ~ŠoÑNÉÃ98Ô§”å œ¡Sš‚sPNviÎÍ:§@´ì˜“´Êv™ “!²dFðˆÞvÈ.Ù³ˆöq'`¤ì¾ÍÙ£hÚmNðqÞ?‰Gñ) k¡-tGâˆüQˆò1GnÈíÙ!ì¤=”•š’³R„BPˆJ¬éU,Ö%šÄºV—JÓB`HLe Œ¡2Å&X¤Ït™î“Mri®Mmi­­6€¦ÐÜ⛜S~oÀN‰ÃÑ9§ tæ(œÅŸÚsûN›‰Óq:Ù'[$ìúŸS¹Âw8Ný©ßµ,§Å€rBÎÀYØöáþÜ\U Š¢&B„Ë.¡eÔ6j¦ÍTô\‹„vƒÑ!r$.F¤èÔ ×¤ô–Ä’Ø’–¢RÔKicm.â¥ÜTÃô˜~“+úeM )¡e5¦°4Ú†›PÓy:o'NIÃé9B§(T羜÷Ó¨òuNÇiØí;§'täðtž“ÈZy O;‰çq=F'¨ÄövžÎÓÞR{ÊOމñÑ>„§Ð”ûŸaÓð‚~OÑ)ú%?~§ïÔþhŸÍêÝPAÊ8¢‚TP{‚pC7øfÿqâÎ<™N)ÃbØl[Ý©ûµD•ˆ’±W£Êô˜p“·ÂVøKÕ‰z±2I¦I4Ò¬šU“hbm NiÀM9K')dé¢4Sµ¢v´OIàé<Ò§šTõÆž¸Óߊ{ñO©óµ>ä§Ü”ýŸ¡ùú?Oû ÿa@3¨uø ? JiPýGܨû•h£í}r®QöŠ>ÑGÚ(ûE%⤼T–Ú’Û£T”j’ƒÞÐ{ÙÅÁ8¸$#„`tÚn›M‹ß1{åÇØ¸ûdJ̉Wßêûý[4«f•`ú¬U`b¬ UŠ£SªbµH"©UJ¢IT ‚áO·)öå<Χ™ÔëzoS“*reM᩼56H¦ÉÓúšS<ªg•L°©–1ܦ;”Ę€Sª`5Kשzõ.ð¥Þº:—GRäÊ\™Kz©oU-œ¥³”µB–¨RÐ*ZK*©eU,h¥°š–R¾JWÉJî)]Å+‚¥pT­*•¥R¯*UåJ©©U5*p¥N©:•'R¢*TEJƒ)Pe)à¥<ãšœsS„ pM驽57:¦çTÚª›USaÊl9Mn)­Å54¦¦”Òòš^SFJhÉLø)Ÿ3r¦nTÌj™S+ŠeqL©‘õ2¦AÆÂ˜ØS*bÅLK)‰e0¨¦Ár˜.Sª`5Kû©u/¬¥õ”½Ò—ºRóê^}KÁ©x9Ç 8áeòÔ¾ZÂÑøZ nÁ-×-úå¿Yþû?ßaÜL;‰xܯ•¾R·ÊV“‚ÒpY"«$U`ý,¥x¯U¿Ò·úVŒ ÑX¬«•]¢«´Ud‚¬USŠªqTu*Ž¥Nô©Þ•0Ú¦T›Š“qQäª<•E¤¨´•¢¢TT=Ї±P¹ª5B¨B•’ ²T J)Oö©þÕ?@§èúŸBSܪ{•OQ©ê5<¢§”TïòþS¸Jw N·©Öõ:\§K”犜ñS–ªrÕN4)Æ…8b§ Tßú›ÿSyÊo9MÑ)º%6â¦ÜTÚR›JSc*leMv©®Õ5˜¦³Õš SPŠjM,)¥…4z¦TкšU{j¯mUˆ*±Tžª“ÕM© Uª£•T *„On©íÕ8º§TÒŠšQS*`¥Jö©^Õ(B¥T‘ê’=RªAG\¨ë•Ú£;TZJ‹IQ=*'¥D$¨„• ª¡µT,J…‰P‚ªUAZ¨+U* eTj€MOà©ü>þ§ßÔùºŸ7SÞ {ÁO\©ë•<ú§ŸTòZžKSŠxQNî©ÝÕ;X§këªuS©Êu9NŒ)Ñ…9â§UG¨à•R£*T[ ‹aQ=*'¥DD¨ˆ•2¡æT3*†eP®ªÕB*¨EUš ÓTŠ‚qP-ªµ@R¨ TÿjŸíS÷j~íOÂ)øE>š§ÓTù Ÿ!SÝJ{©]+¢qØ®;½š·³VÓjÚmZÁ«X5i"­$Uœ¢³”VU Ê¡Xæ+ÅaÖ¬:Õ*°%Uíj½­WRªêU\ «•jÚ­[U•в±V ªÁuVúªßUW"ªäUL ©TèªRšªSUFÒ¨ÚU j¡mSô*~…O©à8 §TÓ*šeS*cÅKœ©s•+‚¥pT¢j”MR]ªKµHè©! ¤!T{JiQÌ*9…F–¨ÒÕJ£ TXJ‹ QBª(UD’¨’U ¢T: ‡APÊ*EBº¨We ¡ázïB$–D’È{ï^PÓÊqÎn9ͯWµêöuΡØüCˆaf,,Å}ï¸uÝþ»¿×)2å&[ ‹tk+­eu¡P´*^ÊËÙXõK©b,@E„¤°”–²À¶Wê*ýE^ó«ÞuyD¯(•Úò»^WEjè­\‰«‘5p®¸r·VÂJØIZ+Rhˆ­›³cVSªÊuXî«Õb.¬EÕƒj°mU÷ª¾õW†ªðÕ\è«nz­ÏU§J´éVXªËX:«U\Ê«™Ud ¬UKª©uTFªˆÕMZ©«U&J¤ÉTdªŒ•P¶ªÕ?r§îTójžmSŸ*såMÀ©¸4ʦ™TÈ*™Rú*_EKD©h•*Ò¥ZT¢j”MRf*LÅI©"•"B¤HTj-Qâ*©œp3ŽLtÉŽ˜·sîaCÌ(y¯/õåì^½‹×’òB]Ì«¹•u€®°Ïf¹ì×$ºä—\9«‡5oŒ­ñ•¹L·)–ÑÒÚ:[ë`=j÷­^õ§Ê´ùV’ÒZë@ýgO,éå™î³=Ö[âË|Y@Ë(dN,‰ÅŽŽ±ÑÖ/òÅþX™ë=aÖ,:Å„ü°Ÿ– âÁ|X ‹‘_¼+÷…|ö¯žÕìz½W–jòÍ]뫽uv®ÀUÑÚº;W.ÊåÙ\`+Œp ®Uº‚·PVÕjÚ­[«`j¸­W¦´ÃV…*Ð¥YÊ+9Ef¬ÂÕ”:²‡VAÊÈ9XÈ+b:¬GU…"°¤VjÀíWç*üå^À«Øx¯UÒŠºQWªãÕ[´«v•l­‚U¤Š´‘Vi*Í& ¸Á7£_tKî‰{Â/xEçX¼ë€êð]–k²ÍtÓ®šuÍX¹« ãá\*‹…Qon-íŹ,·%–ÒÚÚ[[ ËaYk+­eu¨þµÖ•âÒ¼Z!KD)g¼¬÷•›Ð³zcòÌ~YaË,9d߬›õö²Ö9ºÇ7XÃ+ebu¬Nµ‡°°öâÂÜX9Ë9`q,%ʯùUø"¿WÅÊø¹^¦«ÔÕy¯#UÞ »ÁW^ÊëÙ]#+¤es ®a•Ʋ¸ÖW*àÅ[Á+x%mÄ­¸•²r¶NVµêÖ½Z˜+Si8­'¡´#VtªÎ•Y™+3%ef¬¬Õ’²@V:JÇIX²+Eb¬@U„r°ŽV ÀÁWä*ü…^à«Üxj¯ U×jºî/‚EðH~…Рß\ë~ÉÏÙ9è7=çX¸ë]‹£màm¼ «I5i&ƒšÐsYÓ0:d*Ì…YŠd1L†2ÃÆXOà ø`¤Œ‘€\0 …øü¿—IJø–^žËÓÙxƯÕÜ´»–—ZÊëY]K¢)rè.]Æš¸ÓWŠàñ[ÖËzÙnE­Èµ´ì¶–ÄÂØ˜ZÖ«ZÕj~­OÕ¦–´Ò֪ѵZë@ýg_¬ëõšÊ³YV`*ÌYY‹+1dÄ,˜…¨²9âÇÖvîØO; ç`®,Å€˜°ú´¿V—ÌrùŽ^ÅëØ½yk/-eß »ôfúìß]D˨™sÉ.y%ÊL¹I—ÒâÚ\‹‚QoB-èE¹ ·!VÕ:Ú§[KcikŒ-q…ªìµ]–ŸÓàZL«I•hu-¥Ÿ³ãÖqÚÎ;Yœ+3…eÙ¬»5”þ²ŸÖK:ÉgY‹!c˜¬sŒh±)jÅ-XˆËa­,5¥„ܰ›– ºÁ—XËÙ_õ«þµ~V¯ÊÕòú¾_W¶ öÁ^z«ÏUxt¯•ܪ»•W\Êë™](«¥sz®oUÉJ¹)Wêâ}\ +eo$­ä•¸r·VÒªÚU[ «aukH­i©Zµ+V—ªÒõZ%+D¥gάù՛ʳyVbÊÌYY\«+˜Ž³ÖaIœ)3°#uóÕ¾z·˜ñ³=K§©qo®-õ¹7#ÍvÙ®Úà³\jCHq¤q4Ž&€æÐÙÃ;8gf$ÌÄ™•²£6G¼È÷˜îãÜc Ìa¹‰™13&ÜÛ˜O; ç`·Ìù€Ý0¥ûþ¿×ÓÒúz^å‹Ü±z¯@õâ2¼FWrªîU]tË®™tš.“EÍŽ¹±×$Šä‘\Lˉ™p+®u¼Ò·šVäÜ€[Xkk lƒ-e®ÔµÚ–®ÊÕÙZŠkQMiw-.壴`ÖÒÐ:YÝk;­fÞ¬ÛÕ™³#–ZÚË[YIË)9dš¬“UP² 9ºÇ7XÇëýb©¬U5ˆÚ±VZËXWk í`ï¬õ‚2°FVšÀSWòjþM_o+íç`âÌø+nnÍÑ´I¶‰6¼Î×™Ú§Tài€0¡ë´=vxÏ™§k4íeÃL¸i“ù2&DÈ‚Øä;‡bìì]‰Z1+F8ÇOk í`¼Œ‘0"åý&¿¤×Ú²ûV_kàMz–¯RÕ䄼—|šï“]¢Ë´YuO.©åмº—0êæ\«5q. EÀL¸ –òBÞH[‘kr-mo-­å²z¶OV½º×·ZÆ+XÅjh­M¦Î´ÙÖÂÒZ+CegÍ,ù¥œä³œ–j"ÍDY…‹0±e’,²E”.²…ÖHÒɉ³6b¯Ã5ø.}ÏŸÐÓú{qáßÈ»ùc~ìoÝ"[¤Krïn]íÅ•8²¦ÿ(ß奛t³mGM¨é°N¶ Ö®°ÕÖw£NôhÛ aŸ¸³÷p¢ÎY޳1Öes ®a’ô2^†@ôȘÛ{obÒÌZY‰±!öÀÃxOk í`ÄÌ™E°(µþp¿Îà*ü_!Kä){¯aõæà¼Ü†:ðÇ]ËK¹iuÿ.¿åÓ†ºp×<êç\± –!qÐ.:Ãb¸lVÿ¢ßô[ÆKxÉnK-Éeµè¶½Ë¢ÙtZÿË_ùkD­h•ªtµN–ŸÓàZTËJ™h´-‡“ÐòzäS¼Šuð޾Ñmº-·-Œå±œXû‹pnͺڷ[V׬Úõ›cbŒk8­g¨Ï5æ“|ÒoškBgsLîiš¢³TV^fËÌÙKë)}d„ ±ñ¶4ºÆ—X¯»÷b5ŒF±†Ú0ÛFÎÂyØ2ë]`]Ì ¹à¯üùj¿-WÎRùÊ^ákÜ-z3¯Fuãà¼|{êï}]© µ!uƒ®°uÑîº=×7Êæù\¢«”Uq™.3%ø`þßÃ[Ä+x…nM­Éµ¶ ¶ÄÍ*Ù¥‡nÐíÚVÂ*ØC(_q î!zrÏNYã:âÇÜ뀽nÔíÚ¶«¶ÕvÈÔٚ߃[ðj~OѦ64ÆÆŠ¤ÑT™õã>¼g ìá]™@3(Y¢Ë4Y=S'ªdSLŠiŽþ±ßÖ2ìÆ]˜ªcLb'ÌDù†Æ°ØÖðÂ~4Ë™`kŒ q€0¥ú¾¿W×ÔRúŠ^ý‹ß±z©¯U5åׄÚð›]Î ¹Áv .ÄÔŒº‘—BjèM\ÍK™©rV®JÕÅʸ¹W áC{Šïq]çÙ¼û7†ððÞ»û·uw®®õÐ9º7+\åkœXÓ‹p&®Õ»×7zæÝ@Û¨0[f k»Íwy«µcVÈÓ¹@cH h0Í®³µÖk:ÍgY€K0 e] «¡’ô2^†B¬ÈU˜çSêc bÁŠ\1K†!îÄ=Øk aa@l( ƒZ°kVRÀêXø_¿+÷å}/³¥ñd¾,—±ªö5^}ËϹxÔ/…Þð»Þkrín]më­½tÆ.˜ÅÏr¹î_ä»ü—~ ÏÁYò#¾Dw°œöžbSÌJxϹڧ»T÷TLꉜûcŸlr£îT}Å8±§FàhÛÄ+x…mú¿Q³Ñ6z&¿X×ë«XUj$­D•¥D´¨–ˆRÑ Yñ>"g ¬áµ™Š³1V[ÜË{™I+)%d ‘á²Ö7ÐÆúÀ[ b‡LPéˆZ± V€ÃPP› `Þ,Åû0?fXÀKó’þr_|‹ï‘|³¯–uî ½Ä¥úô¿^SëÊ}x=/§×~úïßkà z”oR䯼•÷|L[³ku.£ÏK9ég)xå/YS‹*pB.E¼³7–fáØÜ;H“il/-…å­5£†¦ªÔÕZf«LÕhÕ± b´ VvXÎË®û5ßfÌÃ9– 2ÁfNüÉß™Ë#9cáL|)‘1²&.ÂÅØXž»×b A¡†˜0Óƒ˜9C(`‰Ì9€Ê0Eý࿼ä"ü„_B+èE{è¯}¸Œ÷ž‹Ñ`xÏ/åÝõ»¾·cFìhÝ<›§“s·îvýÊ'9DçŒâÑœ£‚toBÍèY¹· öÔ¶Ú–Ûûbÿk€Ípªµ5V¦èÓ½HCIhhm žâ3ÜFqÎ"#3¤eÚ¬»U•7²¦öL(É…[" cÄlx6±¦Ö-°Å¶›ûb,@ņ0Ѧ<‡˜:£T`’ A€þ0ÅþÞ¿Û×è’ýyÉÏ99â¼@×s¬îu»¯÷tÌ®™•ιÏ÷(åÜYƒ‹0pZî ]½e·¬¶åöܾÛ\£k”l‘m’-®ÞµÛÖ®ÕÒˆ£Qie ,¡¢Ä´X–€xÐØ+;fÇŒØñ˜Ê3FZ<ËG™G#(ädš “A‚2F:ÇRÍë½bËìY}‰Ž11Æ ÄXh# aGL(都°w¶ ÄÁ8ž ÁÁvÿßá×CºèwJÆéXÜâSœJruîN½Å¥¸´·”àÒ›Úû{_n~mÏͶi¶Í6˾ÙwÚû#_dk ­d©‡50æšdÓLš>SGÊhPM ž»³×vqFÎ(Ù¡;4'eö,¾Å•Ʋ¸ÖOÉá“#²d,€ŽC±Èv2HÆI¯»÷bZ¬KU‡ô°þ–ÃB]²‹¶Qu©µ!Ò+:Eg7–æòÜ››“sqjÎ-YÁ˸9vøßÛ¦stÎm¾-·Å³”¶r–Á´Ø6šÕ‹Z±jšÍSY§˜´ó“²ÒvZ%kD­g÷ þá‹3±flüÍŸ™‘s2.eÀŒ¸•2¢†LŠÉ‘Yƒ"°cä |î±½Ö14Æ&˜¬K‰bQ J!ÚU;J§X*ë]££tsg®lõÉž93ÇÎâÙÜ#ƒäo•Íò¹ºÝ·[¶ÝÐÛºCëh}lIM‰)®$5Ć­0Õ¦ˆ{Qiy­/5£f´lÖƒ¼Ðw™ê‹=QgLã)šM³I¶`øÌd{,e £!’Ÿ2SæCrÈnXó[kcfllÍŒ±‚wUÂê¸]û¢¿sY.k%É}9/§úâß\"c„Lo§ ôá»@7hßÈÛùM3i¦lsÍŽy®ìµÝ–°hÖ –‹RÑi·m6í¤X4‹ˆÑÙû[?kgb ìA›e³l¶ešÌ³Yw‹.ñef¬¬Õ“Í2y¦HVÉ Ù ãu<ާ‘Ðüº—4 æ”—K’éqq®.5ÂJ8IFû¢ßt[¹[w+nÃqµb6¬FÉæÙ<ÚùC_(k: gAª?5GæžüÓßšU#J¤h¾-Å º´Vz`ÏLdz8öf lÔ ˜–3Æ[Ë`YP *dÐLš Ôt:އBªèU\ÏÙørTîJÅ×8ºç Âá8[òƒ~Pnþ ßÁ¸Þ·Ö×–ÚòÛ0³flm‚­šµ³V¬>Õ‡Ú‰SQ*iŒí1£ç´|ö†èÐÝù#?$gd,ì…›Ž³qÖfÎÌÙÙ}[/«e‡Œ°ñÐX: 3,æeœ”‹’‘qwî.ý™¸S6ýœß³›Å[x«nS-Êe¶l6͆ΈÙѳaÖk”­r•«Ð5z¥ŒÔ±šq#N$i3­&u¢£´Tv‚FÐHÙèS= g&LäÉš»³Wvc¬Ìuc ,s'dáÉ5¹&·¨âõ,[…‹oè-ý¼¥7”¦æþÜßÛmûm¿m ¡q±Š¶1V¼ׂšÈƒYjŠíQ]§â´üV–´ÒÖš8£Gh^Í ÙŸ|3ï†vXÎË»Û7{só~aÌp9Ž$Àä˜`Œp¶îÝ¿à7üóÈÞy¢+tEmÖ-ºÅ´º6—FÈpÙúK_IkP jªì5]†¢¢ÔTZg³Löi-#E¢\4K†¬Ð5™è{=sã.|eÌO9‰ç$ˆä‘`‹ŒpÁ.%À¸–ôòÞž[§{tïmôM¾‰µ66¦ÆÊÂÙX[`‚kzoQ«›µsv¥¸Ô·tcNŒiM­)µ£:´gV…У\õ‹ž±s ®aµÉ9"çXã 2ã†\p7±†ëjÝm[ƒóp~mk ­a³76fæÃjØmZèC]kbqª µD :ÔZ_ËKùií ]Ï'9äç06æÜ‘s’.qŠn1MÃQ¸j7àB[Üã{œnÌ­Ù•¸¤·–ؔۛ;Ûg{lZm‹M¯&5䯳ÖÖzÚ­‹U±j/­Eõ¦Å4ا;ìç}œÀ+˜rCHaÆ78Æç ÀḠ“ro…M𩻇·pöäÜiƒm0mm¢ ±ø¶?¾ô×ÞšÙS[*jà \©y5/';çcœ¾—ÃrBnHMÆG¸È÷XáË{Ïo–òÑ»×7zæåžÜ³Ûpcn m-í¥½²v¶NÖÁ$Ø$šã\ckaΦ9ÔÇ/.ååÜó’q–2Áï8uçdàŒ›ék}-o -áe¹È79ÝÄÛ¸›S jal¾­—Õ°Ú¶V»×cè+rî]ÁÉ9 ç˜ã3=+‡¥pSN i¾Ø7ÛñÚÞ;[¢StJmõ ¾¡µ¡6´&ÍäÙ¼›Ãb¸s—®rõ˧¹t÷$ä‚g“ŒòpüîÁ|8/†üRߊ[Ëãy|nœÓ‘¸9·6Ø0Û?KgéråÎ\¹É ¹!7ãBAKˆ)pj® U¿K·évôÞ‚Û¬{un%ÍŶw6ÎæÑ”Ú2œ¸ó—rCÎHyÆ—¸Ò÷À⛃³oâÍüY½G7¨æìfÝŒÛKqém¸­·É9!ç¶ãVÜDëˆp€®¿Ä·ø–öFÞÈÛ¶kvÍnTʑƻ8×g¼â7œ#„boüÍÿ™½Ö7ºÆîØÝÛlãœq"®$UÂZ¸KW¾àÛàû|o-àÄ®¸•× øá?C€Èo“ÍòyÄÊ8™G ´áVœ ƒ0q8'ÂиZ æá|ÀuóB¾hWÎjùÍ_.«åÕ|ü¯Ÿ•óB¾hWÊJùI_9«ç5|¿¯—õòR¾JWÐú_5kæ­|ª¯•Uñú¾?WÅ*ø¥_Eëè½|ë¯uòþ¾_×ÉJù)_kãm|A¯ˆ5ô¶¾–×Ðú_5kæ­|ª¯•Uò¾A×Åzø¯_ ëá]}C¯¨uô^¾‹×κù×_1kæ-|™¯“5ñ¶¾6×Äøƒ_kà­{ï¯}õàμ×*ð%_Lëé}¯ õón¾m×Êúù__ ëä|W¯Šõðƾ×ÀZø ^ökÞÍ{­¯uµáê¼=W…šð³^«Áõx¯µõ&¾¤×ÑÚú;_µç>¼çךŠóQ^b+ÌEya¯,5å¼ W‘ªò5^>kÇÍxدâÆ¼X׉ ñ!^kíxT¯ •àμר û_U+ê¥}(¯¥óò¾~WÍ ù¡_)+å%|x¯ñ2¾&W øA^ý+ߥ{ίyÕÑW·jöí^Ò«ÚU{#¯duëâ½|W­õ£^ªëÕ]z¯Oõéb½,W£*ôe^‚ëÐ]yå¯<µæú¼ßW™Šó1^\«Ë•yQ¯*5䪼•Wšò^:+ÇEx¯U↼P׈ ñ^+Ã%xC¯uöZ¾ËWÖªúÕ_O«éõ}¯¢Uóš¾sW˪ùu_#«äu|b¯ŒUðÚ¾WÁ ø!^ù+ß%{¸¯wî2½ÆW¶ öÁ^ÎkÙÍ{¯aÕëž½s׫ºõw^¥kÔ­zn¯MÕé ½!W¡Êô9^}kÏ­yϯ9õ溼×W˜Šó^XkË y@¯(äj¼Wšñó^4«Æ•x±¯5âB¼HW†úðß^+Â¥x3¯u÷v¾î×Ûûc_akì-}Y¯«5ô¢¾”WÏÊùù_4+æ…|ª¯•Uñú¾?WÅ*ø¥_ «á5{ú¯Uï:½çWº*÷E^ÞëÛÝ{O¯iõ쎽‘ׯÚõû^´kÖz«¯Uuéþ½?×¥Šô±^Œ«Ñ•z ¯Auç–¼ò×›êó}^f+ÌÅyr¯.UåF¼¨×’ªòU^BkÈMxè¯ã ¼aWŠñC^ +Äx_¯ õá¼!×ß:ûç_qëî=}›¯³uõ¾¾·×Ô:ú‡_Eëè½|ë¯uòþ¾_×ÉJù)_+ãE|<¯‡•ðB¾W¾J÷É^î+ÝÅ{‘¯r5í–½²×³šös^ÄëØzç¯\õë½`שZõ+^›«ÓuzH¯I膽ןºó÷^u+Î¥y®¯5Õæ"¼ÄW–òÃ^P+Êy¯#Uãæ¼|×*ñ¥^,kÅx¯á¾¼7ׄêð^ ëÁ~ ¯Á5÷v¾î×Ûûc_akì-}Y¯«5ô¶¾–×Ðú_5kæ­|ª¯•Uñú¾?WÅ*ø¥_ «á5{ú¯UïN½é׺z÷O^ÞëÛÝ{O¯iõ즽”ׯÚõû^µëÖ½z«¯Uuê½BW¥Šô±^Œ«Ñ•z ¯Auç–¼ò×›êó}^f+ÌÅyw¯.õåF¼¨×’ªòU^BkÈMxè¯ã ¼aWŠñC^ +Äx_¯ õàú¼!_‰kñ-}ù¯¿5÷6¾æ×ÚûC_]kë­}I¯©5ôv¾Ž×κù×_/ëåý|”¯’•ñ¢¾4WÄøƒ_kà­{é¯}5îö½Þ×¹÷#^ÙkÛ-{?¯gõìN½‰×®ÚõÛ^°kÖ zš¯SU麽7W¤Šô‘^ˆkÑ yû¯?uçR¼êWšêó]^b+ÌEya¯,5å¼ W‘ªò5^>kÇÍxÒ¯UâÆ¼X׉ ñ!^ëÃ}xN¯ Õà¶¼€`M_ŽëñÝ~¯Áõ÷޾ñ×Ûzûo_bëì]}_¯«õôξ™×Ðzú_6ëæÝ|¯¯•õò¾A×Åzø¯_ ëá]{ÿ¯õïN½é׺z÷O^àkÜ {U¯jµì¦½”×°:ö^µëÖ½z°¯Vê½BW¥êô½^ëѽz¯B5ç–¼ò×›êó}^gkÌíyw¯.õåF¼¨×“ òa^BkÈMxè¯ã ¼aWŠñC^ +Äx_¯ õàú¼W‚ŠðP€µ~*¯ÅU÷æ¾ü×ÜÚû›_hkí }u¯®µõ&¾¤×ÑÚú;_¯Õàμׂ*ðE^ +ÁEx¯õøª¿Wßêûý_t«î•}¦¯´Õõê¾½WÔêú_H«é|ö¯žÕó*¾eWÉúù?_ëã|G¯ˆõðn¾ ×¾ú÷ß^ðëÞ{—¯rõí½¸W´Jö‰^ÆkØÍzò¯^Uë½cWª õA^+Ó¥zM¯Iµèž½×  ô^v«ÎÕy³¯6uæ6¼Æ×–zòÏ^P+Êy¯#õãæ¼|׊ñ±^-ëŽx–¯Õá¾¼7×…Jð©^ ëÁx"¯UàJ¼ W‚ŠðQ^ëÀ½~¯ÃU÷º¾÷WÛÊûy_d+ì…}d¯¬•ô⾜WÐÊú_8+ç|´¯–•ò&¾D×ÅÚø»_ ká|¯€µïf½ì×»*÷e^á«Ü5{Z¯kU캽—W°Šö^·+Öåz¶¯VÕê*½EW¦:ôÇ^kÑíz¯B5窼õWœJó‰^gkÌíy}¯/µåZ¼«W“ òa^CëÈ}xè¯ã¼c׊jñM^!kÄ-xd¯ •á¼!ׂ*ðE^«À•x¯µà2¼Wã üa_+ð%}د»ö²¾ÖWØ û_U+ê¥}(¯¥óò¾~W̪ù•_'ëäý|s¯Žuñ¾#× øA^ý+ߥ{ȯyîr½ÎW· öá^Ñ+Ú%{¯cÕëʽyW¬Êõ™^¨+Õzy¯O5éN½)×¢zôO^€+ÐyÚ¯;UæÎ¼ÙטÚó^YëË=yF¯(Õä~¼×êñý^6+ÆÅx·¯õâZ¼KW‡Zðë^+Â¥x3¯uàJ¼ W€ð^+Àewü®ÿ•øj¿ WÞêûÝ_p«î}–¯²Õõª¾µWÓêú}_D«è•|毜Õòê¾]WÈêù_«ã|6¯†Õð*¾W½ê÷½^ì«Ý•{†¯pÕ킽°W³Jöi^Â+ØEzâ¯\UêÚ½[W¨úõ^˜ëÓz=¯GµèZ½ WŸ óá^rkÎMy£¯4uåö¼¾×•jò­^MkÉ­y¯!õ㺼wWŒzñ^)«Å5x…¯µá’¼2W„:ð‡^«Áx¯õßÞ»û×Êïù]ük¿~ ¯Á5÷v¾î×Ûûc_`+ì}T¯ª•ô¢¾”WÏÊùù_4+æ…|¤¯”•ñâ¾kÇÍxè¯ãb¼lWŒzñ^-ëŽx¦¯ÕâZ¼KWˆZñ ^kíxd¯ •áR¼*Wƒ:ðg^«Áx¯Uà¼×ïã]ù«¿5wÖ®úÕß»â×ßšûó_skîm}¡¯´5õÖ¾º×Ô:ú‡_Eëè½|ë¯uòþ¾_×ÉJù)_+ãE|<¯‡•ðB¾W¾š÷Ó^ïkÝí{‘¯r5í–½²×³úö^ÄëØzç¯\õë½`שZõ+^›«ÓuzH¯Ièr½WŸZóë^ykÏ-yϯ9õæú¼ßWšŠóQ^f+ÌÅyˆ¯1åʼ¹W–òÃ^RëÊ]y;¯'u䪼•W‘ªò5^A+È%xó¯u㎼q×*ñ¥^0«Æx¬¯•ân¼M׈ºñ^«ÃÕxj¯ Uáf¼,ׄšð“^+ÁÅx(¯àv¼×€Êð]ÿ+¿åwì®ý•ßn»í×} ï¡]ð+¾zy¯O5鎽1×¥:ô§^kÑíz'¯DõèZ½ W  ô^|+Ï…yÚ¯;Uç&¼ä×›:óg^hëÍy¯1µåö¼¾×–ÊòÙ^U«ÊµyF¯(ÕäÖ¼š×‘úò?^CëÈ}xþ¯Õ㺼wWŠñ±^1ëÆ=x·¯õâš¼SW‰jñ-^!kÄ-xu¯µá’¼2W…Jð©^ëÂx3¯uàŠ¼W*ð%^ëÀ=w÷®þõßš»óW}jï­]òë¾]wº®÷U÷޾ñ×Ûzûo_bëì]}_¯«õôξ™×Ðzú_6ëæÝ|¯¯•õò¾A×Åzø¯_ ëá]{ÿ¯õïN½é׺z÷O^ÞëÛÝ{U¯jµì¦½”×°:ö^µëÖ½z«¯Uuêj½MW¨Jõ ^›«Óuz^¯KÕé"½$W£zôo^ˆkÑ z ¯Auçî¼ýמZóË^u+Î¥y¾¯7Õæº¼×W™Šó1^b+ÌEyw¯.õ冼°×•ò£^NëÉÝy*¯%Uäj¼Wšò^<ëÇxã¯uãJ¼iWŒ*ñ…^,kÅx¡¯5âB¼HWˆ ñ^ëÃ}x_¯ õá:¼'Wƒêð}^ kÁmx¯µà2¼WÊïù]ük¿wá®ü5ßB»èW| ï]ík½­w¤®ô•êî½]תZõK^£ëÔ}zy¯O5馽4×¥:ô§^«Òz,¯E•èZ½ W jô ^|+Ï…y߯;õç&¼ä×›šós^hëÍy’¯2Uåö¼¾×–ÊòÙ^W+ÊåyF¯(ÕäÖ¼š×’ZòK^CëÈ}xþ¯Õ㺼wWÚñ»^3kÆmx¼¯•âš¼SW‰jñ-^!kÄ-xu¯µá’¼2W…Jð©^ëÂx3¯uࢼWzð/^ëÀ=w÷®þõßš»óW}ºï·]òë¾]wº®÷UÞ¾»××yúï?_~kïÍ}ͯ¹µö†¾Ð××Zúë_RkêM}¯£µóƾx×ÌZù‹_&käÍ|m¯µñ¾ ×ÁZø+^úkßM{ïxuî^½Ë×¶ºö×^ÏëÙý{¯c5ë¶½v×­zõ¯^±«Ö5z°¯Vêj½MW¨ªõ^+Ó¥z^¯KÕé6½&×£zôo^ˆkÑ z¯B5çî¼ýמªóÕ^u+Î¥yį8•溼×W™Úó;^b+ÌEyw¯.õ冼°×•ò£^P+Êy*¯%Uäj¼Wšò^>kÇÍxè¯ãJ¼iWŒ*ñ…^,kÅx¡¯5âB¼HWˆ ñ^ëÃ}x_¯ õá:¼'Wƒêð}^ kÁmx¯µàJ¼ W€ð]ük¿wá®ü5ßB»èW|Zï‹]ík½­w¤®ô•Þf»Ì×°êö^¾+×Åzâ¯\UëF½h׫ºõw^©kÕ-z•¯Rµéþ½?צšôÓ^–+ÒÅzB¯HUè²½W¡Êô9^«Ð5yõ¯>µç~¼ïלúóŸ^nkÍÍy¨¯5æJ¼ÉW˜*ó^[+Ëey\¯+•å.¼¥×“Zòk^IkÉ-y¯"•ãú¼WŽêñÝ^7kÆíxͯµâò¼^WŠÊñY^&ëÄÝx‹¯uáê¼=W†ªðÕ^kÂÍxI¯ 5àâ¼W‚ŠðQ^ëÀ½x¯õßò»þW~ÊïÙ]öë¾ÝwË®ùuß»àWzúï_]çë¼ýw”®ò•÷¢¾ôWÛÊûy_d+ì…}d¯¬•ô⾜WÐÊú_8+ç|´¯–•ò&¾D×ÅÚø»_ ká|¯€µïf½ì׺Ú÷[^àkÜ {Z¯kUí½¢W²êö]^ÆkØÍ{¯`uëʽyW­Êõ¹^±«Ö5z°¯VꂽPW¨ªõ^+Ó¥zc¯Lué6½&×£zôo^‰ëÑ=z¯B5è½WžªóÕ^u+Î¥yį8•æÎ¼Ù×™Úó;^ckÌmyw¯.õåž¼³×•jò­^P+Êy0¯&ä~¼×šò^>kÇÍxè¯ãb¼lWŒzñ^,kÅx¡¯5âB¼HWˆ ñ^ëÃ}x_¯ õá:¼'Wƒêð}^ ëÁx"¯UàJ¼ W€ð]ük¿wá®ü5ßZ»ëW|Zï‹]ík½­wª®õUÞf»Ì×xêï]ß«»õ{e¯lµí>½§×³šös^ÈëÙ{¯buëö½~×®zõÏ^´kÖz»¯WuꮽUשZõ+^ŸëÓýzn¯MÕéb½,W¤*ô…^Œ«Ñ•z¯C•è.½ןZóë^ykÏ-yϯ9õæú¼ßWšŠóQ^f+ÌÅy‚¯0Uåʼ¹W•Êò¹^RëÊ]y;¯'u䪼•W‘Jò)^A+È%xó¯u㎼q׌Úñ›^/+Ååx¬¯•ân¼M׈ºñ^«ÃÕxj¯ Uáf¼,ׄšð“^+ÁÅx(¯àv¼×€Êð]ÿ+¿åwì®ý•ßn»í×} ï¡]ð+¾w¯®õõÞ’»ÒWyJï)]àë¼wx®ï÷J¾éWÚjûM_^«ëÕ}N¯©Õôо‘WÏjùí_2«æU|Ÿ¯“õñξ9×Äzø_ëàÝ{ï¯}õï"½äW¹Ê÷9^á«Ü5{p¯níj½­W´Jö‰^Ë«Ùu{¯cÕì"½„W¯*õå^·+Öåz̯Y•êÚ½[Wª õA^¢«ÔUzy¯O5鎽1פÚô›^kÑíz'¯DõèZ½ W  ô^|+Ï…yÚ¯;Uç¼âW›:óg^hëÍy¯1µåö¼¾×–zòÏ^U«ÊµyF¯(Õ优W‘úò?^CëÈ}xþ¯Õ㢼tWŠñ±^1ëÆ=x·¯õâš¼SW‰jñ-^!kÄ-xu¯µá’¼2W…Jð©^ëÂx3¯uàŠ¼W*ð%^ëÀ=w÷®þõßš»óW}jï­]ñk¾-wº®÷UÞª»ÕWyúï?]㫼uw~®ïÕÝλ¹×»Ú÷{^éëÝ={‘¯r5íî½½×¶ZöË^ÓëÚ}{?¯gõ즽”×±:ö'^¿k×ízç¯\õë^½k׬õƒ^ªëÕ]z•¯Rµê½BW¦êôÝ^–+ÒÅzH¯IèʽW¢ôC^‚ëÐ]yû¯?uç–¼ò×Jó©^o«Íõy®¯5Õæb¼ÌW˜Šó^\«Ë•ya¯,5åF¼¨×“ºòw^J«ÉUy¯#Uä&¼„×:ñç^8ëÇxÒ¯Uã ¼aW‹ñc^(kÅ x¯â¼@W†úðß^ëÂýxN¯ Õàú¼W‚Úð[^kÀíx ¯•ßò»þWïã]øk¿ wЮúß»àW{Zïk]é+½%w™®ó5Þ&»Ä×wŠîñ]Ûk»mw]®ëµ÷¢¾ôWÛÊûy_d+ì…}d¯¬•ô⾜WÐÊú_8+ç|´¯–•ò&¾Dׯ*øÅ_ «áµ| ¯Uïz½ïW¼Š÷‘^ì«Ý•{œ¯s•î½ÃW· öá^Ø+Û{J¯iUìÒ½šW±êö=^Â+ØEzò¯^U늽qW¬Êõ™^­«Õµz¥¯Tµê>½G×§šôó^škÓMzS¯Juèö½×¢ÊôY^…«Ðµz¯@Õç¼øWªóµ^rkÎMy¹¯75掼Ñ×™*ó%^_kËíyl¯-•år¼®W”jò^MkÉ­y%¯$µä>¼‡×êñý^;«Çuxݯµã6¼f׋Êñy^)«Å5x–¯Õâ¼BׇZðë^+Ã%xT¯ •á¼!׃:ðg^ +ÁEx¯õà¼×zïï]ù«¿5wÛ®ûuß.»å×{ªïu]ëë½}wŸ®óõÞ:»ÇWx:ï]Üë»wh®íÝ^»«×Åzø¯_kâ |+¯…uðV¾ ׿ú÷ÿ^úkßM{Ó¯zuîö½Þ׺z÷O^äkÜ{¯p5í®½µ×µZö«^ÏëÙý{)¯e5ìN½‰×°:ö^»k×mzׯZõë½`׫ õa^¦«ÔÕz„¯P•éÒ½:W¥êô½^’+ÒEz7¯Fõ膽סô#^~ëÏÝyê¯=UçR¼êWœJó‰^k«Íuy¯3µæ"¼ÄW—zòï^YëË=yQ¯*5å¼ W“ òa^F«ÈÕy ¯!5ãæ¼|׎ŠñÑ^4«Æ•x¯UâÆ¼X׊ñC^$+Ä…x€¯á¾¼7×…úð¿^«Âux>¯Õà¶¼×Úð;^«À•x¯5߯»ø×~ïÃ]õ«¾µwÅ®øµÞÖ»Ú×zªïU]æk¼Íw‰®ñ5Ýú»¿WvÚîÛ]Ø«»wR®êUÝ»£×ÝŠû±_k+íe}€¯°õR¾ªWÒŠúQ_?+çå|Яšò’¾RWÈêù_+ãÅ|b¯ŒUñ2¾&WÃjøm_+á| ¯UïÒ½úW½ê÷½^ò+ÞE{¸¯wÑW¸Ê÷^ݫ۵{`¯lí*½¥W³Jöi^ÈëÙ{¯aÕëâ½|W®*õÅ^´kÖz»¯Wuê–½Rרúõ^ŸëÓýzi¯M5éN½)פ*ô…^‹+Ñez¯C•è½WŸZóë^wëÎýyϯ9õææ¼ÜךŠóQ^d«Ì•y‚¯0Uå²¼¶W•Êò¹^RëÊ]y5¯&µä–¼’בJò)^A+È%xó¯uãv¼n׌Úñ›^/+Ååx¬¯•ân¼M׈ºñ^«ÃÕxj¯ Uáf¼,×ÌZù‹_+ëå}|™¯“5ò¾A×ÆÚøÛ_ëâ½|A¯ˆ5ð®¾×ÁZø+^ÿëßý{é¯}5ïf½ì×¼:÷‡^ëkÝm{—¯rõî½À×¶ºö×^ÕkÚ­{D¯h•캽—W±šö3^ÀëØzí¯]µër½nW¬jõ^¬+Õ…z ¯Tê*½EW§Jôé^˜ëÓzM¯IµèÞ½×¢zôO^„kÐz¯@窼õWªóµ^q+Î%y³¯6uæv¼ÎטÚó^]ë˽yg¯,õåZ¼«W” ò^L+É…y¯#õä>¼‡×šñó^:+ÇE}Õ÷ ¾áWÙjû-_Z«ëU}>¯§ÕôJ¾‰WÏÊùù_9«ç5|Яšòê¾]WÊJùI_#«äu|x¯ñо1WÄÊø™_+áå|&¯„ÕðB¾W¿ª÷õ^ù+ß%{ίyÕîâ½ÜWº*÷E^ã+Üe{v¯nÕí–½²×´úöŸ^ÎkÙÍ{#¯duì:½‡W¯Úõû^¹ë×=zѯZ5êî½]תºõW^¥kÔ­z¯Oõ麽7W¥Šô±^«Òz2¯FUèr½W ºô^}kÏ­yå¯<µç>¼ç×›êó}^j+ÍEy˜¯3æ ¼ÁW—*òå^XkË yK¯)uäî¼×ÑÚú;_Aëè=|ñ¯ž5ón¾m×̪ù•_-+å¥|Ÿ¯“õò&¾D×Ç:øç_kâí|G¯ˆõðƾ×Áºø7_kà-{ï¯}õïf½ì×¼:÷‡^ëkÝm{—¯rõî½ÃW· öá^Ö«ÚÕ{D¯h•캽—W±êö=^Â+ØEzò¯^Uër½nW¬jõ^­«Õµz ¯Tê*½EW§šôó^˜ëÓzS¯Juèö½×¢zôO^…«Ðµz¯@ç¼øWªóµ^rkÎMy³¯6u掼ÑטÚó^_kËí}ݯ»µöƾØ×ØZû _VkêÍ}-¯¥µô^¾‹×Ðú_:ëç]|Õ¯šµòþ¾_×ʪùU_%+ä¥|~¯Õñ¢¾4WÅ*ø¥_+áå|&¯„ÕðB¾W¿ª÷õ^ù+ß%{ίyÕîö½Þ׺z÷O^äkÜ{{¯ouí–½²×´úöŸ^ÎkÙÍ{)¯e5ìN½‰×¯Úõû^¹ë×=zׯZõë½`תºõW^¦«ÔÕz„¯P•麽7W¥êô½^’+ÒEz2¯FU膽× ºô^~ëÏÝyå¯<µçR¼êW›êó}^k«Íu}8¯§ôо‘WÐÊú_=«çµ|௜ó*¾eWËJùi_'ëäý|‰¯‘5ñξ9×ÅÚø»_ëâ=|1¯†5ðn¾ ×ÀZø ^ý+ߥ{Þ¯{Õï"½äW»*÷e^ç+Üå{†¯pÕí½¸Wµªöµ^Ò«ÚU{4¯f•ìz½W°Šö^¾+×Åzâ¯\Uë2½fW«jõm^©kÕ-z¯Qõéæ½<צšôÓ^”ëÒz=¯Gµè²½W¡jô-^«Ð5yð¯>ç~¼ïלšó“_[ëë}}Y¯«5õ¾¡×ÒÚú[_Eëè½}¯ 5ó®¾u×ÍZù«_/ëåý|ª¯•UòR¾JWÇêøý_+ãE|R¯ŠUñ¾ ׺øW_kà­{ÿ¯õ尿ô×½:÷§^ïkÝí{§¯tõîF½È×·ºö÷^ÚëÛ]{U¯jµìþ½Ÿ×²šöS^ÄëØ{¯`uë¶½v×­zõ¯^±«Ö5z°¯Vêj½MW¨Jõ ^+Ó¥z^¯KÕé6½&×£zôo^ˆkÑ z¯B5çî¼ý×Ôêú_N+éÅ}"¯¤Uô2¾†WÏjùí_8+ç|ʯ™UòÒ¾ZWÊJùI_#«äu|x¯ñо1WÄÊø™_ «áµ| ¯„ð*¾W¿J÷é^÷«Þõ{ȯyîʽÙWº*÷E^ã+Üe{v¯nÕ킽°W´ªö•^Í+Ù¥{#¯duì:½‡W¯Šõñ^¸«×zѯZ5êî½]תZõK^¥kÔ­z¯Oõ馽4×¥Šô±^«Òz,¯E•èr½WÒÚú[_Gkèí}¯ õóƾx×ͺù·_1kæ-|¯¯•õòf¾L×È:ù_kãm|W¯Šõñ¾ ׺øW_kà­{ÿ¯õ尿ô×½:÷§^ðëÞ{­¯uµî^½Ë׸÷^ÚëÛ]{U¯jµí½¢W²êö]^ÆkØÍ{¯`uëʽyW­Êõ¹^±«Ö5z°¯VꂽPW¨ªõ^+Ó¥zc¯Lué6½&×£Úô{^‰ëÑ=}¯¢Uóò¾~WÎjùÍ_4+æ…|º¯—Uò’¾RWÈêù_+ãÅ|b¯ŒUñ2¾&WÃjøm_+á| ¯Uïê½ýW¾J÷É^ó«Þu{¸¯wÑW¸Ê÷^ݫ۵{e¯lµí>½§×³šös^ÈëÙ{¯aÕëö½~×®zõÏ^´kÖzÁ¯X5ꮽUשZõ+^¡+Ô%zn¯MÕéb½,W¤Šô‘_½§×³úö^ÊkÙM{¯buëö½~×®ÚõÛ^µëÖ½zÁ¯X5ê½XW©ªõ5^¡+Ô%zt¯N•ó*¾eWËJùi_'ëäý|‰¯‘5ñξ9×ÅÚø»_ëâ=|1¯†5ðn¾ ×ÀZø ^ûëß}{Þ¯{Õï"½äW»*÷e^ç+Üå{†¯pÕí½¸W¶ öÁ^Ò«ÚU{4¯f•ìz½W°êö^¾+×Åzâ¯\Uë2½fW«ºõw^©kÕ-z¯Qõéþ½?×ʪùU_%+ä¥|~¯Õñ¢¾4WÅ*ø¥_+áå|&¯„ÕðV¾ ׿ú÷ÿ^úkßM{Ó¯zuîö½Þ׺z÷O^äkÜ{¯p5í®½µ×µZö«^ÏëÙý{)¯e5ìf½Œ×°:ö^»k×mzܯ[•ë½cW« õa^¨+Õ|Ÿ¯“õò&¾D×Ç:øç_«ã|L¯‰•ðÚ¾W øA_«àU{ô¯~•ïz½ïW¼Š÷‘^ì«Ý•{¢¯tUî2½ÆW·jöí^Ø+Û{J¯iUìæ½œ×²:öG^ëØuzø¯_ëž½s×­õ£^®ëÕÝz«¯Uuòf¾L×È:ù_kãm|W¯Šõñ¾ ׺øW_kà­{ÿ¯õ尿ô×½š÷³^ðëÞ{­¯uµî^½Ë׸÷^ÚëÛ]{Z¯kUí½¢W²êö]^ÆkØÍ{¯aëʽyW­Êõ¹^³+Öez¶¯VÕñâ¾½§×³šös^ÈëÙ{¯buëö½~×Äøƒ_ ëá]|¯‚µïþ½ÿ×¾ú÷ß^ökÞÍ{ïxuî¶½Ö×¹z÷/^á«Ü5{p¯níj½­W´Jö‰^Í+Ù¥{¯cÕì"½„WÃjøm_ «á5|¯‚ïê½ýW¾J÷É^ó«Þu{¸¯wîž½Ó×¹÷#^ÞëÛÝ{e¯lµíV½ª×³úö^ÊkÙM{¯buðƾ×Áºø7_kà-{ï¯}õïf½ì×¼Š÷‘^ì«Ý•{œ¯s•î½ÃW·jöí^Ø+Û{J¯iUìÒ½šW²:öG_ «á5|¯‚ïþ½ÿ×¾š÷Ó^ôëÞ{½¯wµîž½Ó×¹z÷/^àkÜ {k¯muíV½ª×´Jö‰^Ë«Ùu| ¯„ð*¾W¿J÷é^÷«Þõ{ȯyîâ½ÜWº*÷E^ã+Üe{v¯nÕí–½²×´úöŸ^ÎkÙÍ{ÿ¯õ尿ô×½š÷³^ðëÞ{­¯uµî^½Ë׸j÷ ^Ü+Û…{Z¯kUí½¢W³Jöi^þ«ßÕ{ä¯|•ï:½çW»Š÷q^éëÝ={‘¯r5íî½½×¶ZöË^ÕkÚ­{?¯gõïf½ì×¼Š÷‘^ì«Ý•{œ¯s•î½ÃW·jöí^Ø+Û{J¯iUîö½Þ׺z÷O^åëܽ{¯p5í®½µ×µZö«^ì«Ý•{¢¯tUî2½ÆW·jöí^ÙkÛ-{O¯iõî^½Ë׸j÷ ^Ü+Û…{Z¯kUîF½È×·ºö÷^ÙkÛ-{†¯pÕíÚ½»W¶ºöÖ4,«Þ *÷‚Ù˜¶cæ+ÛºŠöî¢é–Pºe”,ÈÖ 25‚¯ëh«úÚ-Æ q‚B¾xx¯ž*ˆŠ„""íœH»g,àp‹8"¯ @«Ã)0 DLs縜ùî0 ÂÞÊ·²¤+äOŠùâžž§§¤'ÿš ÿæ‚b3à˜Œø1C¿ŒPïâñ*¼J„,îc ;˜Â­pH«\(͘Š3f"mˆð›b<$öÕ‰=µc* ÊŸÈ0T~Œ¢àÞ°¸7¬+×oŠõÛâ›À¦Ä0'›Ó æôÂYÀð–p<#²Óì´Â臀z ̆ó›o &ÛÈ1¶Œ m£ô·à½-ø,ñ› ˜'O¦ Wu‚UÝ`Ž#…Äu‚E €Ð( 4 «`êØ tÏp3Ü7¹îCãGChÑÐÚ1>b O˜‚á½à¸ox+d ÅÙƒ p È%v‚ ] ‚.£‹¨Æ ƒnˆ Û¡äh0y 4‚ ¤Ö°i5¬‹á†"øanÊÈ[²²oÍ[óAAxPCÞÌõ³=AG¨òƒª< ÜáH78R †A¡€Ä½x1/^ œöç=€¯Àx+ð eÓ™tÀ”p'e UPUT¸#cndü‚? Šâ€‘¡äh@rÿð¿üÔ͵3@gÞ`÷˜6º £nƒ1hÌDZ/­ ëHÆ„h±¡)E Qp‚dó°™<ì#…ÃápÂÚXƒ¶–†â‡¡¸¡Å\HqWLX†“!†Ýpa·\»R…®Ô¡R²0T¬Œ»#îÈÁ&µ0I­L9„NcaÓÐ@tô¬ƒÆ« ⶸ8­® MUƒSU`ÈÈ2ò ÆÎñ³€±\p,W sÆœñ€êH'z’ S*‚TÊ Œâ#8„SÒô€~X„t©Ý*@pëÈ:ò°R¬ ec8XÎ_€ÃŽyØãžv5*š J¦ƒ…ÅáF-ä‹y⧉¨©âj':1 ÎŒBCl˜Û&!eψYsáìýx{?^nq‡œa¤^ˆi¢I\†W!gÀXYð×s…5Üá5ºhMnšüÑ4A 8CŽž£ƒç¨àé&°:I¬ žßƒg·àËê@2ú ð¥‚ü)`³NH,Ó’ ƒÝ‚ ÷`ž.ð'‹¼ L»S.ÀŒ#>]—@|c0ÌRTÔ•n’ø¤¾…h¡Z b’@¤ÐtÀWÆ€ñ ;”åCxâXÞ8–3‚Ð à´ùz°¾^¬+Ø‚Šö ¢„«@¡*Ð$öÕ‰=µbh臚:¹‡ÅîaÈqèrz2˜†Œ¦!nø`[¾0ë…Œ:áG˜Qä&èÚº6ÐFt5ê z€ðíð<;| ü6ƒ  Ðh`4 #ƒÄ µ@-P –¥†Àžbp'˜œ E8QNŠð@"¼%° lz=àx-ÙËv`kÓ(ôÊV3•Œà_7ðÍü˜Mf@T8°,ò<€@JL“B껺®ãêyÈúžr:J½’¯C^™8צN1•IŒeRbÖ¾ µ¯¨){g ^ÙÂ]‚@—`"t-ˆ aö}‡¦‡'i¡¡ÁhpDÚÚ…ö¶¡](WJ=A&+àIŠøï†;á€ù¶¸>m®j¸ƒš® Õ^¨5Wª [ïƒûà·v-ݤ ¦2‚©Œ ž„À'¡0 9kNZÀ‰˜ð"f<’‚¤ wåùDÊÀ2€h½ˆ/bV‡U [˜øæ>ZV„ Oÿ8ÿήi+š`EðH|„jâñ¸¼B+Šð£×³@õìÐ8´Ž-c>òÈϼ²/M£‹Óhâ®”«¥&ÔD‰µ"1bèŒXº²8ìŽʆr¡„ö„}¡xƒà^ øg7…YÍá7½`MïXÉQ„rTa` Aêeº™@Û 6À( š)ƒ&Š`¹­.kD ¸p®žs˜'œæ +x‚JÞ ‡ëÈ!úòßó÷üÀuð@¼Ê²„ dü8?Þ w‚`W,ËDG€KM˜Ófa*J€AXGŘ€ñf 7ì û$>xžyŽÞc€1"} HŸB°¨@¬*%ˆ¿ b/ ‘8‚äN‹i"ÚAÙ°cölóÄ|ñ5dMY$ à„H8 óz@<Þ Úcö€ÂÐ0ƒ´ Ýý·@œ+ð' üÍ‚3C ~Í0³L)ÊcÀg™°ælÙ¿voÀT°Ø,6ÊN2“ E3xLÞé€ú@ 8Sä-?ËOÀ-™ f@ŒP€£ $Fè º×€5À:ø¾ˆ­b+@0€L vG€ §ðiüZœÑ§4EarÑX\´P²`,˜§M¡)ÓhClÛ#c¾|ÈïŸ24Rô ½Òì(´» &«‰ªß≄b@\4‡ !…þHa’P…D!$ÔˆI5"ùÕƒþu`ßåÀ7ùp SZÖ€®$x+‰ ¢‚h£àˆþp"?œ›IæÒ@l¡((Jô‚=V(‚ ͆3a DTPÍóFÀ5é˜ zfûå¾ù@)ú ~‚M€“@à p\»nÆ€‰PâT<€€O :8ŽÐ$4 ÛpvÜp§€)àJ¨ª0H )S JTÃàÄ x%È¥r)`WsÝÜ÷EÍéE3zIèM’zdWiÚ8 Î(3ƒ/HÀ Ò(&: Ž‚NȆ²þÝÿ·Ax•^%BêXú–N8CÓŽŠè¢ºÈ¡2(F ØŸ‚¶'à–Ψ%³ª7í û@rÌp³Cöý€WÆ€ñ ÊN2“ Bý¿@¢1èŒ@2H £Ò¹`®X%H` RüŒ#Уt^Õ€Wµ`‘ˆdbÞ€7…  1HŒRmo€[à°(ì à8(–4J%a±D˜lQ#ŸìHçû(ÔDŠ5!ilHZ[½ŠDob‘×$FµÈ^æ`—¹˜%“EAdÑPQöb”}˜¤:ù#ξ>𼦝#?7xÏÍÞ*{ ‡žÂ6è‡Íºi»†Únáe"àYH¸Z(„–Š ô7= Æ Å1E«ÿ(*ÿÊ sGÀ{¦`阑5¤M`Ys¨\êÄñ1<`@“$Àjf€Ú™ -Ì€ s ^.—‹€ÇFŒøc>r0܌櫀9ªà ì˜{&`€#à6€¡˜hĦ1&_¼I—ï9þÄŽ± ñDH~à ¹nFGâ€ø eûÄ™~ñ"ÀÄH°1ögD}™ÑaüGœGÄgñ'EÉÁPDTÑÜdD·©DCªQ ìCÂ{ÕÌD5s ¯œBëç¢LÄ(“1¼LB/÷DýÑ*@ŠÄÇf°AY¬Vfr…Ü…ìt9{S¼7ï Ä>Ù°æ2õŒ…=b0r˜Œ¦°[†,áQðGT| ==ƒOO`Ÿþh'ÿš¢Ëè²à]#ÈHòqBP€5`@ Xs£€œèà9xÎ^ÎE3€ cHXÒ"U€•q&¤dI©ÎĆs±Ú$G6‰ŽUDc•QyÜE^w%0ÄIL1¤lCéÐnÄ4± ÐtB´ŽüÄ#¿1$AÃÉW2DÌ‘ù|@þ_+5D ÍQ9´@Nmÿ8ÃÿÎ0þàÜ?¸7ÛÐÃöô0ü»Œ?.ã¼³Ãï,ðûAä>ÐyT¡ÃÕ(pôôL==pÃ0À†Áá°A8d®ë…S€ATà<|î;‚<ÚP6”_µWí@×Px5ÔØÛ‚66à^G˜‘æÞE€÷‘`'¸ Á®[€Vç`úÈþ³»DŸîÑ™ôGæ}Œ0Dc ÜdD·ÞaD7˜Q tB€gJDÒ‘T@àUPDÔþ­d?«Y˸Ãòî0û”>Çå˜9CæPø=l>[q™ÃÜfpõõÄ=}qQiÃÔZpô7t= Ý7ªCÍêòÎô<³½ ÃÈðñUT45 h-ÃZ pÍ0Ä3L1 Ù|C6_ÎC:3Ψ¹¤*.iZ_Å–ªy°*žl ]9‹WNbñØåxðÙOƒöSá!HÀR0 ALSv9ÀÝŽpI±ül…Áa@°db…è"Áº°w(œÊ'íëAûzÐ…‚,!`‹¶ŒÂ-£0l$ [ TCBUЙŽÔ&cµ ÖÂu…0 ÌÌ(33 (±ÂŠ,p¤Ä)1 Z –‚ð§ <)ÂO †¡‚0©É *rC ¯à«ø0¬3+ Á Ö€Bµ ®+§A ùç¾yð°ÂT,0• OÂÇSð²´$,­ 4/Ï üxÂÿ0†-Ô!‹uŽÚB#¶‹yô"Þ}Ý,B7K<¼$/ '3ÂIÌð”Sä%ù g“BYäИH¬&+ ¡‚Âh`°›ç¤&ùé Ø:BvŸ¤'Çé ¹Â‚îp¢$(‰ :îÂŽ»°¥<)A c³Â˜ìð§’Œ)ä£ ‹Â£bð©üŒ*# ²¬p¬U\+W ÔZµ°®XT+– ö°B½¬°[T,Õ §ÂÄéð²*Ì,г .zBËž³µ¤,íi G'BÑÉе/L-KÓ ^ÁÂ×°p¶—Ä-¥ñ t7BÝ Ð·Ýì-÷{ ˆ™Ââ&p¹ì.D» šÖÂæµ°ºGì.‘ú£cq(ØÜJÍ( ³JºQ0.”L ±Ôã,u8Û h¶Ã.rƒœ† ïq»ÜCïR1ÃÔŒpù7¾MÁ¯Âdzð±ìþqû¿œ~ð}ßA¢rÀhœ°,í´ ;mÉé@òzPJô†=ZÁV†0_Ž$㉃HÁ Ò0oÙ„öa9¬ÁÎk0vãô¸ýŸ™AçæP}<CÏþAÿ€Ð‚  ¨S×Âõð‡§|!éß Â(0Œ6Ä# ±åÁÂ9ppl$ [ %BIC”B´%­ b5ÂXp—Є%ô! ˜íBf;P›*Ô&ʵ ÊGÂr‘ðž/L'‹Ó û¡Â~èp¡D(@ &ŒB‰££®ì(ë» N>“°¦*)Š… tÞB7¨q¼*o ˜FB¦ª¨4*ª ¸u®p¬w´+í Õmµ[p®6+ ñR¼T°¯Ñü+ô ÿÂÂð±\Ô,W5 !šBÈf²ÅL,±S 7BÍÃд-Ì- s L„ÂÓ!0µsô-\ýðLÁ|0bùœ¾goùA›þPj¯´«íãØA¸öqdTYIÄÁÒq0w±ôì}¨.Áê °}SäTùþAÿ€Ð‚J4 ’MhBZ†ûÔ!¾õ“$Â$É0‹Wœ"ÕçÔ–Â5%°;D#ÎÑ ÑBD´P’ëd$ºÙ K®BRë–VÜ%•· ~Â_†°™}¬&_k ®bÂk˜°œN¤'© Ü„Âw!0Ÿ¤'Çé IÂRp¡«ô(jý .‹ƒ°¤Ä)1 R‰B”¢P¦ì)†; q¦Bœi¨ ¼*¯ ŽžB£§©ëd*zÙ «•ªåp«˜„*æ! ÆhB±š­4„+M! à(B¸ ®®,+«‹ ÷½ð°°¬,ª¥Ý„)wa Ö"µ„È·Wp­ÕÜ,6¦³ ©¬ÐN›´¦íÀwkpÚåk˹ZòîÈ»+².ÊñàhÁ™O°iÐŒt#ÏuÁ³Ýpp/T Õ3<ÁÌÏ0vÌ3\AãW{bØ…ÜÀÁ÷00€X\ 'ÛB öЄ´,!- nªBªˆÜ|"7­÷B+}ÐŒÀ#0çæÂ9ù°_$Å ÃÂH0ð“— $åà S0ÂTÌ0–¬´%«- ‚eÂ`™p™ &h ¯uBkÝPœN¤'© ÙLÂvS0ž¸¤'®) ýÇBqСD(@  ‡Âp£D(ÀÑ @LB¥<)A ^V—•°¦Õ¼)µo {NBžÓ¨‚ä* ¹ •B¥Cªä*‡¹ ®Í«³p(£ (Åö@½£P5qÌ \s´sÀíð@“\$×\åA9PJ¢L¨“óA<ÆPSžŒç£y5Á^Mp[ª|êŸõªA}jbƱ‡e>Á™O°iXdVÇóA±üÐor„Ü¡$7ÁÉ ðtò$<‰wçAÝùÐyù”~eÇKÁñÒð~š ¦ƒB†Ðƒ ÁÁOBãP‡ ü!Ã?ŽÚB#¶Š«ô"ªýÇ·B1íÐŽ(œ#Š'üIB?P‘`”$X% -£ÂKhð”e %C ]ëBWzЗ6%Í ‡ÂÂað°™ÂT&p• ®bÂk˜°œ ü' ÑÊBtrž@|' ôB}РTœ(' aÂ…Xp¢5D(Q 3lBŒÛ¤Ä)1 OQB“ÔP¥Ã)pÄ­ðö«|=«[ÈjÖò¿/ÁÇ ”SË%òÓƒ]4à×MËÿûrÿþäw-¹Ënª8“ªŽ$»âo/6ÄËͱ2ö‡N½¡Ó¯õCä=Pû&²¾É¬¯ÎƒÃó ðþ`Ñ?˜4Oú´Cþ­8ã@8Ð 4œ ';sÀNÜðKÒÁ! ÀˆC0(´< -ìåÀ»9p4pL ¢6Àè°?*äʹAA@HŽ$#‰ΟA3§ÐQE¼QoQƒAT`ÐXê¬:«LJÁqáð_ãôøý3äAŒùfe™E–˜Á¥¦0lK´íð¸A¼.qº$n‰CTÁÐÕ0v°t¬”Aä%{?¼Ïï×cÁõØð›ŒæãèBzƒ¡„ èaX"°‡@|!ÐÿÂ$?ðŠ«ô"ªýÅ‘Â1dpõ#}GöìB=»ù”$>e &!BIˆP“¨<$ê OøÂSþ0–#\%ˆ× v˜B]¦˜|,& ›ÂfİšÃÔ&°õ ½gÂoYðœé$':I Ý—ÂweðžÚô'¶½ û¡Â~èp ªt(* ™Â†&oâKËø’òþÅ«?±jÏõ½óýo|ÿçY?ùÖP£Ô¨õèÖÀ:5°—äeùÉÀrD°"ÞÄ·±‘³À¤lð.¬ «@”ÀÐ%09UlU[àpÀø0B¸´®-p5A PK_×ÇöQA=”PS<ÅOmhÁ[Z0Z0ÔŒ5زAv,`ÔL5;fÁŽÙ°f̳—«A¥êÐl:„¡î’Á»¤°qAüP<äÁÏ90v'‰Ç„ÆÁá1°z‚ì »È^Aò~ˆä¢9½Â/p‚[\ –×B­B«P…úT!~•yeBYP‰Ct"Pݯ Â+ÂpŒY#GÝ,B7Kì#Æ; ÂB°‘¶d$m™ /ÈÂKò0” d% UUÂUUp–y4%žM yÐB^t˜¯¬&+ë šBf€šÃÔ&°õ º/Ân‹ðœ¤|')´ÎX­3–+Äþñ?†Ä¬H±+,Ö ›5‚¦ÕÉðµr|-Öëuƒºãçi¸ùÚn•]ë¥WzíÕ»uD¯ScÆØôŒç½#9ïqq+Ü\Jù9+¾NJï°¾ì/€ûÔ>õ OÉ{òc^ýF¦?Q©ÞàK÷¸þŒÎ?£3ñ·ûümþÿ¤Ô?é5%´‰m¼À'o0Ãì0ûx›@^&Ðù¤~i<ñÀÁ‹é°búlLS#ÓÐj€´ -xP«^*Ý÷"·}È®9Ö#Žuˆèo3:ÌÎȇ«²!êðæ<y/ÛËÇöõoH½[Ò/hÛëÚ6ú÷“‡=äáψq+âJùh`¾Z/£ïCèûÐû]¾Áo»Îkîóšüi¢¿h¯ÐºCô.ý£ý¿hÿoã*óøÊ¼þ¼?¯Ïó©Óüêtÿ²Æ¿ì±°H ’Ý@$7PŽìã»Xk@VÐ\,×  ª@ƒ*&'ì ‰û±ã@¬xÐ/¾¬ ï«GÀÑÁ08©Ä*qÎ3ÀóŒð@ÆÜ1·J¨AªHZ¤©¼aÁ/pO1”Ìe'«ÁIêðUddŠ`Ab˜[vüÝ¿å’Ayd`öœ=§9AÁŽPpf<ƒÏ†€Á¡ 0jã4¸ÍÑ›A´fÐo-ÔËuEAÅ‘PsgLÙÓV¤ÁÕ©0w\×’¹Áä®pzû¾ÅÈ^Aò~3 ŒÃüðÁÿ<0H´ R-,% p„*Ô! µY5BMP†ê¤!º©„Â!ð‰vô"]½«ÑÂ*ôp‹àô"ø=Ñ_B4WÐŽ9Ä#ŽqõÙB=vNÀŒã°#8íÁ»pp®öBû½¾ðÜļ71/$1ËÉ róŠW<â•ÏKŽKÒã’õÓ=tÄmž³Ûg¬÷Ή=ó¢OŠý{â¿^ù‡}¾aßo¤¬é+û º¾Ân¯»VCîÕü]Õ?uOÏtóÝý‹P?bÔáJKøR’þ–v?¥ñƒüG`ÿ„¤?á)ÿeãÿÙy^p@œ 4œ ' ¡@H(P¬ëÒº@t®"DD‘s©@œêP+Û öø@Áî4´ô -=ŒÁÀã0p<ã<8Ï HÁ’0DT¬+zïÁ»ðK+œÊççLA9ÓQy<^OJÁR€0W_Ü×÷£ AhÃP\ð¤<)øâA~8b+œŠçHFÁ’°fÝ<·O“`Á¤Ø0kJ4ÒÖøAµ¾o”Ôå5jAÆs‰¤âiTAÕÐwDÁ‘ŒIÁãpz`”˜%¿ÉAïòP}‡daÙñ#AüHЀz´ ­3BŒÐƒ:„ ΡJ0BŒ…×ü!uÿrõB½PˆdL"™”Â&e0н"¯G¼üB/? –0"匿X¦/Ö)Œ[ªcê˜ÌF~³Ÿ­,#ëKúØãß¶8÷íç(KyÊão?¸ÛÏî[)³–ÊlçË 9òÜ4Û§ 6ë”ï:å;ÎÓíë´ûzîÕ~;µ_WÛÁöñ¤SÆ0»½CîïPüM½¿ooÍúsó~œýfÖ?YµÞ4£÷(þ_¾¿—ï¯í[ûA–ÿ?ú?Ïþúo›þ›ç æ@9£Ô¨õÆÀ1 pÖ”u¥pÀ\pÔõ —@‚åÐ%Yì V{šHÀ¦’0-ï4 {ÍRÀÇÔ°5Ǥ q陡Àæhp=¼E¯ [AÖÐCþÜÿ·rZA–JLt“ÕA5Cˈé:â:N½Àó¯p<ì5 ³ B¬É½2DoLî·»;­îÔž›5'¦Íu«]_êÚ06€ Èar@ÞóC·¼Ðî¿Ã„ïðãaM8ØSNW“•ĤçW-9ÕËN’ž¤§†êÑ«º´jîÆÉ[±²Víáò»x|®ô•Ó½%tð—¼$%ïÀSÇ0òê{<ºžÏ?ÁÏðDôûi½>Úo^ïS×»ÔöÐC=´Ïz\CÞ—ømR¾T¯’³“ä¬äùàŠ¾x"¯¨~“ê¤û'Å>ÉñO»ß“î÷äüNÐ?´Í_óóWüýYö?V}Ý3+÷LÊþI6¿’M¯ëŒ³úã,ÿ#¿ÈÀ¯ø þ(ÿé~?ú_~„¡žÏÀ'³ð[lÖÛEÀQFðHRÞ‡Àw¡ð"fœ™§m9@›NP*ÙŒ ¶cï À»Â°2±ü ¬g4ÀÙÍ-,¾kK/šÕm¬5[k õ›_ýfÚܶŸ÷-Î#s…ß-37ËLÎ9k…NZãe—¸ÙeîUv“•]¤ç-U¹ËUnކ󣡼ê„l:¡Á;°EŽí|;_Žíœ‹»g"𓼤ï´kÅ-òkἚøo7’ËÍä²ôv`=˜VHãÕ’8öB¤=©q¤«Üi*÷áÙ=øvO‰ûûâ~þùQؾTv/ŸØ#çöú^>§W³[{ìÖÞûÆŽ¾ñ£¯Äþ+ñ?ŠüÒÇ?4±ÏÔó»õ<îýÇe?qÙOã^sø×œþ¥{¿©^ïð¶ƒü- ÿn¿Û‡/ü·;ÿ-Ï'¸@ îǤñéÑ<@4O ‚…k»@ZîÐ~„ß¡ü’@$‹Èòâò<¸Áx™°^&liòË|²ËÛ4²öÍ-–#DeˆÓ°l´ì-b–ÓX¥´Ø6'D ¯^ kׂÝ:O7N“Íö-ƒ}‹`áo{¸[Þî6À{°åD9QNpk[œÖè±·º,mî¤@Ë©2ë¿ÙºïönÒQë´”zîq¶»œm®û(¾ÊðÙŒ¼6c/nûÇÛ¾òú“<¾¤Ï?“Ïãdô᩽8jo\@«×*ö–S½¥”ïv£Ý„hø¶>­ŒÞ#ã7ˆùvS>]”Ï¡…KèaRú³æ>¬ù´:£í¨ûÐ6¾ô ¯Å ƒñH üÒÇ?4±ÏÔŒ»õ#.ý¼ª¿o*¯âKøŸÒþ“>?¤ÏïNûÓ€ÿV‚?Õ û=“þÏe ®@kø,~ ¯ú@+þŒùOû>SþÒ]´„×mGÕ‹QõbÖÙa5¶XM’ÍKd³RÛeu6Ù]MØV“v¤ßš¢7樎鋆:bãn-8Û‹NS„Ôá0æé¾9ºoŽˆ[«¢êêå:¹N·{­ßÞìÑo»4[îá›Ë¸fòïOÍ;ÓóOƒÁÁ ñˆnFº[Ñ®–õI»½RnïaÀKØpöã“=¸äÏyõCÞ}PøR€> ¯ãëÆùŸ>gÆ£wèÝÆúÉ[>²Vϵ*ûíJ¾ûÙÞ¾öw¯Åv[ñ]–üÒÇ?4±ÏÔ6ãõ ¸ý³¿lÀ¯áäËøy2þ„9?¡Oî]³û—lÿA ¿ÐC/ù²Ãþl°ÉjɲZ²l½n£/[¨Î8P3Ž gÛBYöÒô«´½*íT ÃUp×­5ßëM›/ fËÂÛϬ¶óë-Ýo3w[ÌßÐG7ôÎÛc†¶Øã{ 8ÞÃNS ›”Ã&æÍÙ9³vN…ñ³¡|léÑ@:tP³›Ó¬æôì‡h;!Ú܃+· ÊîöÀ»½°/ScÀTØñ!n¼H[¯"Q#È”Hóe¼ÅYo?ô“Ïý$ôÙ½6E/ZµÛÖ­vöm޽›c¯r·SÜ­Ô÷ÚV½ö•¯ˆq+âJù%Û¾IvçjúTi¾•o­þ3ëŒûeÿ>ÙϾI“ï’dü^è?ºÍ,sóKýD€¿Q /ÚÚ[ö¶–þ·?…mÌÏDÓ3Ñ4ÏCu³ÐÝmJÃF°Ó¾_´ï—í_pWÜØ¼6ï ¢å+h¹JÜ0;· íâ«xƒêàƸñ®;àモ8àèŽRêC”ºæº‰9®¢Nƒ‡» áîé¥C:iPί볫úììG»Â.×Àcµðî¤#»©îûÓþôððÈb<2Y[ÇVò²±<¬¬O9„›Îa&ômʽr¯SðÔüö2=€Lk¾ Úï‚÷lç=Û9Ïf³àY¬ø·Z>-Ö•.»åK®ù⯾x«ï§ëéÁ:úöj¾½š¯·r›íܦûïS¾ûÔïÆwÓñôü׿5Ämp@ÜÒ^w´—íH^ÛR¶Ö›'5¦ÉÍŠ8bŽÚžù¶§¾mÈê[r:–Þk·šÀn/»€Ëîáï(8{Ê9LËŽS2å*Y¹J–njÉkš²ZèÎ:óŽ—Ù ¥öBêÊ(º²Š.ÀÑ“°4dí8n»N®å¡Ã¹hpïlÄ»Û1/(ÛÁÊ6ñh>Âø¸–sî%œûýF>ÿQ2é³LºlÕ4Ï5M3ÍsŸ\çÀÙ*¯6J«Í°èãl:8Üç²79ìêØkz¶àjŸ±n õ{ˆ=^ã¤ä¸é9.RÙ”¶Fæ¡Ü9¨w€>“ ¤éYºVE®©â»ªx®ëÕNºõS®Ïçó³ùüî—»…åîò«¼†ªð%N< SZÄV†ñþr<œ-È‹Ër"ó¯ä<ëùGª«Ñêªõ8‘=N$O_£×Ähö¡=¨Ct†ÓÝ!´÷é[½úVïˆSâÔùÄ>Eq™ñƒæ|`ú&G>‰‘Ϫ_;ê—ÎÕÝ@µwP-|¬s_+Ù§#¶iÈí·XÓmÖ4Ý?¬7Oë ïã{Äxà—Õ¸%õn"³Óˆ¬ôã¹G8îQÎRêC”ºæ”ü9¥?+ëŸÊúé7Ô:Mõ§xéÞ0ë¢áºè¸nÌ£³#híØJ»v®íòc»|˜ïÛF»öѯ ¹£Ã.hñ¬è,:“è“äú$ØPã¶8í¡ÓhctÛÜŒ6÷# جcv+ß/X7ËÖ Óƒ tâM’8“dŽ<•ó%|å59MEhèÚ:0ç⦹ø©®‘òs¤|œêSº”Än·¡Ë­èrì”H;%ÙöÛ¶}¶î¡þ»¨®ùŒ¾cð€€< PcÅ”ò;™¼Žæo0™ƒÌ&`óʶ¼ò­¯H¬+Ò+ õ<Û½O6ï^»Ó×®ôö¾½£o¯r٫ܶj÷Åô=ñ}…ácÀØÕí65{M¨‡j!ÆÜ:ö7½Ý‘ƒwd`ßl·Ûîu#ƒÝHâoç8›ùÎ=¨›j&å8L9Nh×›š5æçÐi¹ônxˤ2ê5:AεS­Aìe;DÎ־㵯¸îeé»™znõ¨{½jð=û<~Ïô›Ä}&ñïm<{ÛO+´cÊíó~Š<ߢC“‹Ðäâôè½:oYo³Ö[ìö8ü½Ž?/m|[Û_÷lç=Û9ͯ^ kׂÜË7$2Íâ«xƒêߪº7ꮎ4ó„<âŒÞ¸£7®>ÿë¿úå@á9P8NhÆkš1šçů9ñkÎCË£Ðòê׺…5î²ð+¬¼ ì;;;ÎÎÓ˜´æî4;#ÎñÖ¼u€ðæ<y ©óÃj|ñ­û¿“ϯäôœÿ½'?ïTh;Õõçr½yÜ­µšƒmf Üç²79ìæžóy§¼ßßL7÷ÓôÃ…=0â®!8«ˆN@#ÃðåNÔ9SµhµCš-Pç½¹ïFnŽË£ƒ²êu:€N°¹³¬.lì®;kŽÐés´:\íÿý;ÿNîž »§‚ïÇö»ñý¯ ÆSÂq”ñm›¼[fï# óÈÃ|òîż»±o:AsÎ\ôPÓ=4ÏO¶›Óí¦Û»J6îÒÓ‚›tà¦Þ«a7ªØN¤ë€i:áy#¸^Hî,Óã‹4øä±9ìNUek•YZæy¹£^n{j›žÚ¦èÔ º5.žZ+§–Šêôº½.¿¯À„ìç÷;9ýÎÝQ+·TJ;®!Žùó¾Düðe­¼koÓÃÄ´ðñò¥<|©O*¡»Ê¨nóa’<Ød@±cÐ,X݈¡7b(MîÞc{·˜àMÎ8sŽR †”‚âín8»[ŽBÒc´˜åa9XDNhùëš>zç°9¹ìnŒa££héÕŠºub®­»«`nëÒºô…®Ì7˳ òíª(»jŠ.è¦Cº)ï`÷»Ø=ïÞ3À·Œðö„¼=¡/F³ÆÑ¬òlô<›=1ðÓÌ|4ÝÑ•·temòä[|¹à„…¸!!nÞ[‡7–ã S8ÂTÎDL ‘åo¹[Àîi šBÆç¯'9ëÉ΋Ç#¢ñÈéÃMºpÓn«å»ªùnë¶1ºíŒnÊS²€T탈»`â.åæs¹yœï0°;Ì,ÿÈ“¿ò$ðÀß¼07ï¸ãÅî8ò1ò<Œ|áÊûxr¾ßm’·Ûd® LÓ‚Ó4áò`8|˜2ÜÛŒ·6äY#9HÎWÏc•óØæ–¹¥ƒ®z¾óž¯¼è°¥:,)N›U³¦Õlê« ºªÂ£®dèìå»ùnÖµ€„î6´»­.ð:¼€ïÍT;óUÖÂ5€ñFû¼Q¾íæ&Ëy‰²ß§‚7éàŽb{ƒ˜žâ7¸‡ î4›+&Êäm…¹anXÐã–48柶¹§í®z‹sž¢Üè«Gº*Ñîšv‹¦¢ê˜Îº¦3®¸Ë®2ìe;DÎÓË“´òäî'»„IîíÐ »tï D»è/Á@Þ£Þ·¨÷­ýôÃ}0á¸Eàn$>£‰¨ãfª¸Ùª®H@Û’6å˜Û9f6ÎjQCš”P稷9ê-Ί€û¢ >é››:fæÎ¨iªFënOºÛ“îÄ’Û±$¶í®»G«®Þ¹«·®jî·s»­Üî÷f˽ٲÞä>7¹Ž“»€dîáC~¸Pß®&†K‰¡’モ8àèŽIºƒ’n å¨ó9j<ÎjÉkš²ZçªÜ¹ê·.Š++¢ŠÊé‘ó:d|Χ‰ë©âzëWǺÕñîà °Âí¤»@).Üû[·>Öî‘æ»¤y­ò3|LàIƒ¸`î…Æ„âŒÞ¸£7®:+óŽŠüä±9,GN[n[–Û–æµ+¹­Jîzòsž¼œèŸzº'Þ®˜s‹¦âêi™ºšfn´X«­*ìø»~.Îs³ŸÜí¯…»kámõú}~€àM¸ SnÈ»†r.â°F¸¬®;ÇóŽñüäÇ¥91éN\^³—¬æ¾Ó¹¯´î{ËžÅ2èœBº'®—ûc¥þØê^ß:—·Î³hS¬Ú샻 îÌô£³=(ß–W·å•î ;«‚ÎêáÅP¸qT.-:ã‹N¸ãÜ®¸÷+®MÑ£“thåÖ¹u€®lv“›¤ç³q¹ìÜn‰³¢lÀéyF:^QŽ¥BK©P’ë%ZºÉV®¿$k¯ÉßÏ47óÍQKƒ”RáñM¸|Sn/qc‹ÜXãön¸ý›®OË“Åòåå9yBm›DDç¶©¹íªn‰³¢lÀésé:\úN¤–›©%¦ëºÆcnM“€dáI¸En!¡+ˆhJãX¸Æ.A%;INåß9AwÎ_R—Ô€æÛ˹¶òî|ŸFèš:&‡N— ¥ÂÄê?Â:ðŽ›…fâ@²8,Ž3ªÛŒê¶ä,¹ îQµC”mPæJ¹’®ny‹›žbçÄœ9ñ'‰Ä+¢q émy:[^N£•#¨åHámV¸[U®&Rˉ”²ãYʸÖr®D‹‘âå/¶¹Kí®a2«˜Lªæóf9¼ÙŽ|Ÿ›Ÿ'æèU:'UN–’㥤¸â‹Ì8¢ó7}SßTäa¸¹n.TRÕ°æ#B9ˆÐŽo¿³›ïìçÑ|9ô_‰æƒ¢y ã˜¸æ.G¦[‘é–åX{¹VîcWû˜Õþçµ¹Á­n}m›Ÿ[fã¶8íƒÎISƒ’TàålÞ9[7Žd%ó™ |畹Äån}Ô›Ÿu&䪭9*«NX6c– ˜æRw9”Îqåœy@äÄm91NYI –RBæa|¹˜_.MâË“x²åª¹jn[Ä3–ñ ‚$øùú2 ý’,ðBFØï²@é*PÈÜòWÈÛâ@HÛ2BPùz[PìŠC€ú2CÁ‚=’Œ˜ê²<ØçÊ> ‚D1+’M99sHøò|¹J*Hè¢R@øb8¹*`™-gIš]‘ªy! HP®LñÒQÙ’[©*G-2Y’]AÊÉ⎃`ì{kéúFir; Hý*Uù"^!mª|}9‚–ÁÒjIãF(å3CñQxñ³\0ò’X@ðê^É1zB!RUiêo¡Ú_A z`Q RY‘j}9$¢Š¹ ò–±òzùCVPàÓQøÜ»9î“7P÷LøóÛ_`óci(öúoá2wÉ BÑZe¡*Úq‘ŠI1âkxú}é ’zqAú“2JsB¡ãíèâsˆûÛ9£"Ñ»6óDpò;1 ò“i+%0ÿ I óÓghï[wØò…iÚ^1šWÙ"~Éi$B|ù øòÚli "sP÷¢m ýj‘9$’±ê˜XëªàHÜzæ˜úôèùZÚ Þªï˜×Ú×Q:ÚÙí8õ‚þHëcÀí"íYÚé‰ [!s(A»=Ñ“7€ý A³9 S"yCFˆøcbÀôƒq¨øÚY¹ bpé- E±úZɺnÒx1j„rzXú iqš~xà‰O±7º‡É ªÂxð’éR¦ñ¶xèªË æZ½ ýRÊèÿŠÖ) zÙ ýû˜ð+ªèúôxüó™ó1aû8ùË*¹;'© 4IëA9“JÉ“V9òGa ªi‘5*j +ZQyêa¹.eázt9êtðöb€¸õšpàônÁ 6©>*nj‚i"¢dQ1Êki'ª…áÒ© b·ÂÊàøÎÙ ÒÀ! "ò ûhúCˆñc¸ô»Iá 35¹S4Û3Ñ›: 6‹21C?©[yD8êx $JOI@:‹ $’o‰Úh™¢øç:/¹"²™ððŠy±ÂA7Ú¬Xàš¡ùÂnQ/Ú”Áò·¨óâ½Húrº@üêµ°øR¶€ûJ¿Ñ:àXÿ‚í±k)KpÿsÉó™S#Y›AÃÁ[') 3,‰#+ Ë9‰#Q™j«yL ’J±²Ž%6ÁNÂ|á R†XóòYB«ÈêÊu‰$²`Á(ʿٺ°Á"¦©ʨA ²µþz˜A ¢µ¹B¾xõò«ðþZ«ªÓ9jÚÉ’ÞùË¡ÛXøË@ÿa kI «Ñ [á Ë Ë'Q6q»C‰²¬¹ºU‘FªâÚú†¡2’\'Š•¯ñšzéb€¡‘ Žy'šŸÉ:®0÷j”Ù:|‘ ±Q–éªQZ±) ± ʬqrËq$šâi¢ç9 *è±zè! ¢í[© QÃ É ñ»áãA#“*Ñ"Ë>é£AiâZ ¡/QFy!,J A%bjRJ†Y<’¾iÒ¢±2[yß±I*Úp„¢iby¿¡-Q’˜ ‚=éeºv+¢€ašX‰3 k‰'Òw!v™&ò}™&|Ñ"€9buÁ w #2œqÚ”RžY ¢˜qÄY"©‰/Ò±Ñ0‚¶¡'š·‘BÓ1)òã¹4Êèi)²×‘7 ãA"ÿa0êÿÉ'Êþy-› Á0“ 0k5c5É=»Š‘D3ðYK’lISá¢m;Z²azYa.r¥q’ka!u90rx±+Òri;²w962|Ù>ªn©DZ|1?š›ARŒÙ *ŽY)²Œá)r™á0B­A#z®$òÆ™²Ê‘/BÆa>Ú°™8r·Ñ(j»á-‚Ïé3èù%Úãq-:âÁ>òð8úëù3²ñ:› i=ëñ9ó ©3».Ù1³„É9êÙFŒyM[Ø);d¡Dzš¡Ú)F1©WZtqN’\ 2‚C‰)Â.Ù$BÁ%q!4ªm2Jƒ9,ê†I0RA.Ê¡'Òx‘#š‰Ú†™-Ú‘á4B§q-b¯Ñ"r½'"¬é0´1?r»1;²±*êÄi7²Ò9>âá3âÒ‘6²×Crõ!=úù¡8¢ôI>ãñD›ÁCëù7›‘%{]!!‹»)1;êÉ;t!Dö)@´"‘Fk))"k™!Êl1P +yJŠbé3"`‘9z€ëâZ‰4Šb™<êx,p982R€ùŠ‹A(â„Y:ªˆi7ZÑ&R‰™,j‘a5 ®y/ZÄ)-"­é9Rºi<²À‰7r¶™9’¿H*åERàyFr×MÚìFõA=úöáB*ýéH2úqQâô VsyGÃ8™4“|¡4³ÒAü!GŒ/AJ“ßYH ÉK’ qh MaA"cQ4r|éH²u3"/Oʹ±¢f‰!p™'âá3Š‹ar{yrkAšyÁ6:wñ<âŽ+ÊA-…?*›a@â·@*«IAZ­É=±aMâ¯ÉJB¨CšÑ)A2à!ER߉Mºõ‰GRñáCúéÁL*óYMòóQPrí1]’ýÑ`#$¹OûSùBƒ•CSðII\!IKäéIÄ1¡KRÔ LR_)P‚@™/bE)Jjm‰/RpÙ V¹$‚ѲFÑ7ŠŒéÂd©;š)2Ú|± º{é)Êh:Z„AŠÙ@Їù9jw±F: ù;ê¬É;ZÑ,ú®ÁA¹‰NR³‰M¢ÀC"ÝÙF*á9RŠûáG‹ ÙB ÷¡JÊë Q²ç!RJæyRÂðùS+P3"ÑN[S)O£¥ÑNô yM,;ÁMÜ‘Td:1U2„A.€9‚n)#úUyAâW™(Šb¡‚–$»˜ìºe1)‚HA=ZbA.Òy(‚€A<ê~A*byñ5Š”ÉCB‡i ™¡<²´á8ª¼D²³)BBʹ<úÖPŠáyNrîDZ÷qD‹F»©RIX“ÉQS ÉKà R£Ù^3RAaû©!^D)]L*_+ì‰el yhb†á9Jlé-²ù,Rfa úgé4Ú~q0‚„É/Bš #úR%‘@²r±.:uñ;ÊzQA¢|É.R~!9‚‚)F*}±Kr–qG˜)@‚ ¡HrªÁG‚ ¹A*ƹ=Ä‘HʾYCš½>JËéDÖ)G¢ß)NÃ1NsQO+QV+TÃqN›‰NKyRã2éWã`A\³—¹c“Í kãåncÇÙqbbñ+ŠuáDê[I@’~*zl?:hÙ7ª!4J™¹Òg±"â@y1Ê£Yêva2‚¡7ú‘¹7âŒA6ÚŽQ>Ê”y?R†iKr :Ê”Q?ª­EB  NâµVR¿QTâ·ÁUêÈ©L¢àqNÂÚ)XÂð9Z«Ñ[«"^«4!Y{BñS«;‘Wc4‰[#AÙX»[áX«uq`‹lS°As v]‹lÑaRqr{Y1Ê1Kò{ÙAjkYAšV7âuaF"s @"•Ù‚k!Y\©JjQ>2Y=º¢1;š‚!8Œ"ªŽI7šžq;•iJz¯±5ʤ 2Ò§K’µ‰\¢½U»áQÔùSsÁU«-1^‹E‘^#ly_yIcSƒIf‹‘)ec¢Ù_[¸áVÛËÉPKÕ‘NóÕ)RûÍqYËÁy_˶áb«°Áaó®_k° ]SºI_ÃÊ™ikÔ¡n3à¡q›íIs+ûYrÌñpÓŒIWË QU›´UkÇ)XsÒÑ]“ØéaCßé`KéÑZSø¡QÔ 9J´9HŒñK´R$¡XtQ[Ô9[+ú¡XköYUëõÙU“ûy]Ä d, ±j,Én¬Éq4)¡qÌ2pä9éo*}a$¢‹)Úg9 ‚y©BJc‘92‹‘6Ò„‘L y>ª“é?B8zZ_!6"paCÚŠÉ?‚‘)FbŽA>ª›QAÊ™!>R’ÑMò‡ÁT²£QKZ½AIzܱ^K aYË‘_ƒKPÓmKK‹aM+¦ÙQ»ÅÉR#ãÑMƒûH\ G4)Kt$IRä'1Y(9Z<)V4.1O45qI ; F¬>ÑHÜ@YMì@qRÄ>ÙTÜáaÜIh4QálœYYnÜ]Qo|_inü_‰n1éRÛSÉQsr1O+ƒYTk‰a]Ó˜ù_ë¹aUãØùHKñYB|ELñH¼,ÑFtAá@ÄN‘=ÄT™@¤U)H$RéPOaT¼L‘ULaR,NYNüOÙMœOñNÔOÁQÔP™T,S T$UÙPôW!KŒVFTB´R±C4TÁGlZ™NddAV4oÙ]ŒyùctYg¤ƒijŒilT{ÑmlténiÁ"zcÉ J !B‚l‰Cªk©/Z‹!:ÒŽ9JÊ‘Kâ“1SòuÙQºlù:2=±SJqÑF¢aJŠ‘IG¢¥yIÂi=jšQY °9QƒE U‹†±M3­)H3ÇqHßÁHÓô‰K±QD ÉW¼ ¡V¬4ÑLÔB B$Ey>,HA?ÔRÁ@Ä`™?$i‘>j)@œdF,[!L$QùP¤KñSJaT”LñVQaX TyZ,U¡[œV[LW™XÜZQT<\¹N<]¡H\]ACü]yBL`¹C¬hÑGtuyLŒ… QÜ“©VüžÙ[Œ£A` ¡d<˜©hDŒ¹k䀡n¤vypc•9T{ã¹U, Lô(±Hl5±Kt?©OlEINÌJéLTSáK”]ÙJÜbÉG^B4Uy>üRQ=$WY<<]á>^¹C´XáJüNùOÜDIPô;‘Pl7!QT8áTä@‰ZtJy_¼Rñb„XaaŒ[)]l\Wt\ÁQD\KäZÁH Z±EÔ^IEdg‰F,vÁG¬Š‰I„žÉK´°N\ºIR4¼YW$¶],©cÌ™Ái¼Š9n„}ñqJ§©@Š~Ñ8b[)*‚”¹ª™¡(’QéDy:l!B¢˜™Câa1P¦é?úOÁRªiSŠ€^ÂqÙ]Ò•!HZ°!NòÙU«C1\ŸáIëîÑG$&QQDBÉUÜOQRZQQLc VÔb9X¬[YP4WIDŒX¡?„YùA TñBÌKALBA<Ü@8BÙ7ÔD>lAùIt=ÑRt9!TD4!P´.ùLì,‰M,/ñRT9aYlEi^œQ1_äYq\¬]ÙV´^ÑPt]AK¬Z™HÔXÉGdZ‘F´biF$qEd…‰DdœÑC¬²ñC´Ã¹E„̱I\ÌQOtÃÑW,¶_L¥ùf¼–YlŒ‰™oÛpñV«•A]ûÜSŒ"YC4Mñ@¼[JœVaQìU1SL`V´g\aYYtTAK,K¹=H‘8,EY:ô?y=”8©;Ü4Ñ6œ4Q2¬3Ù5t2)?Ü1aLÄ3TÌ79TÄ8¡OÄ6Kl3QK\3ÙOL9©SÔBñVDMaU V P´[YL]QH”\ÑG [‰FÄ[áF¬`yEìk D,{A¼¡?,¦Á=dºá=TÈÙ?|Ï¡D\ÎKTÇ S„»q\®‘cl¢)hü—ùl¤YbwÑ.jfq!Bd zsùÊxñ)R’ajbÉ.Âx±6ÂkéDú¼I3"Š¡YJ‹‘5ú©EŠ‘W£HkQ;#½ÁBkñQMä ™T¹QL;9P¬<9OLAAL´HQIOaFTTùEÉI´B1MìH‰SLN¡X¼Qù]dO™`LIQ`dBá]?1Vl?QNlBGãËÁC$ Y>´2¹Cô^9CÜ€1=ä|á@Dr‘DLxÙ?ìnQ?ÔJG|/‘J´5iDtP;ìb™<„`ÁI¬VÉXlR]ŒR[ôQ^TMyf”M¹jÌVYdtbYXÌgéR4cùTl\ÁZ\¹[df™UìsM´xÙIlqùMtaùW¬PùbFif¬E™bäKYY¬QéPLU©K„UÑLìUySlWñ[¬^±b,i)d\taa¼|ù[¤¹TŒ€‘O4{YMlsOTkqTnù9\ká9iY;üVA?¤CéABQC,KáFÄYñF¼e±EŒgùKbUl[a\lX)_lWùb´YQe´]‰c¤gY[TsRtyN„u‘PDnAS¬l¡S¼s¹NÜ}ÙGä)DTx¹GTg¡O„VXMé[ÜO™Z WÉU4`QœdiRdÑVôdÉ^Œg‰edohÌ{QgL†Ùa¤iYÌ‘¡R”9NŒ‚éNÄvSiÙYä`Yaœ[™hd\Ál´cmdmikyéf¼†ÁaT‘)\„—QYœ˜9YD“Ù[£0éI3T!U[>Ña³RYë•QTã·9R“ê‰=t:¹,ôù%$¹é)@,nÉGÔ\™M´YTìa!PÄi N„c™T„Ué\¤NÉ`ÌT _l^QZ”fYU”miSvR })P$})M$vùJ¬qAI|qAHœuéGÔx‘H sáJ´háNô]¡RôX!TäZ¡TôbÉTÜkIV|pÙZÌs9`Ütáf”y‘j,ùiüŒÑeÜ–ñ^üœÙWœIPÜ•MìˆùNô{yStoqYüg`ücÁfÜfiÔm±iÄyf¤…ya¤‘Ñ[Ì›‘Vœ¡ St¡S<œ!UÔ“YZÊDÁ+2a1.¢“Ù<Ê7QZBLÙ+¡ ÒÑù$ó$ÉHëNéQS~éJã±yK»ß¹\;ûùlsöqh±\$%yPÜ$iFŒ‰D4GÉ8¨É¬´™$ÄwiA”s@üyÑEÜkQMTn!B4ñ8Œ~ÁA”aáM„VyF¼l¹8Œwy>DbñStR^\Y!Z,déU¬^©Y„L‘`´FYb„SQ[´dqR$k)OLkTtn Y|uQVtyM tÑDäkùCteÉHf1NºK±Jêºa&[ä`iT;¡T´H‰7¬aY+_ÑA”léU”qÙVôKQYt'!RŒùC¤ QÛá©`³ýYI,1YBìEÉNŒn9C<†±>ÜwG qyF\~ùGŒ‹Q¼…9\ y Zü‚©M\’aB¬†ÁF\hQQ$V™X\‘[´hi`hùeüdyiôk±f”~ZL‰aMì‚ÑKÌs‰SlZ™@79Eä79D$4ÁG[úYh+ÜÑ€”%9[ p©7<€±C,†YO”1OeùUüW‰^Œhù[4†ÉPT–ÑKÔ”™P\’±Tü˜9R<”©L ~Müf9YL_ábYetain ‹h¬3AÜM±zLPÑf4OiF¼+Ñ0„/ (4Vñ.”_ÑJl_ÁZToQRÄsHlZa>DPá5¬Ué9Ì];ØyƒÛß©zT¹]$5áW”:Ù]|DRdPR 2YpD0Qq|uÙN±!B¤±ÑY‹ñoŒ_‘pôC™cì>Ù_¤M¡h¼(!•Œ;ái´>1?l4,3º6ÚAËÜ4Áz¼‰{ÿ™ŽTi‡Ì&Y‰Ü3á’¼T9ŒŒw©}4…9uL…ÑlÿÿûÏÿúHærãš±êƒÐ)¤)á}D Q•ÄÉŽ\ ì0ŒD£Äi©–ŒŒ9{d—Ém—ÿù·ÿù&•î©‚ƒ¬°ÓÔ¡—|—Ü ¡—|I‚Ô‚Ü+Ñ ”J9¬ŒwI’t˜¹uŸÿøÿø]INÛqÈÓÁ³ôQ–”!Á‚Ìù|äa<%9¦dP)¡4y…7ÿø$yёêãû©§„6ÁzŒ8ÙsÔ9tq’,)Á—ŒXqФñ}vLh·”1ÏÃõÆ<8ù€”VñjDÙv´"é‚왃Ü6ù¼\q{´!ùÄÔF‘Ü^Ñp `ÉuœIɼ1Ùyœ0¹p„BÑrd¹~´`¹‚ü[1Œ L|Aim¼A!hìTá” Qé „PA™K~„JùjÌM nüDɰlD9™ÔFy}$RQq>Y®49É•\E)~´<±¢¼7!Žü@Qˆh7ñè¡ @l€Húj#Úèº ?|€I"$bÈO A€Iâ$b(æ ?<€HúÊ$(L A¬€IR$Dˆa DF€HÿB$(  D€IÊ$/(‘’ D\€I‚$kèG A:€I ’$]hê Fö€IÒ$/¨Þ J €I ú#ðhF Bä€I¢$VHÔ @â€I *$^èu BT€IÂ$ˆ‘¦ ?f€HûÊ$èŽè @Ü€Hùj#à( >ì€Hü’$ˆ] Bv€I j$^h\ D”€I’$ ( ?Œ€IÒ$ ¨< ?€Ib#›ÈŽ· Cò€IŠ#ÕÔ @¢€Hý²#ìÈÐ ?&€Høª#ÙhR Eì€I‚#ùè# Bl€I’#Óˆ† @@€Höê$ (ŽÆ >€Ir$NH‘3 ;†€Húâ$B(¦ @~€Hÿ²$Èü Aœ€HúÚ$Hq ?F€Hö:#äˆ ¸€Hö#ªèŠ B–€IR$&ˆŽÚ =´€IZ$-ˆ< ?:€Hüâ$.ÈŸ ?ø€Iz$%(¨ <€Hú#òn =Œ€I$ 8 >6€Hÿ¢#Çh, @š€Iò$H ?X€HþÂ$H5 :Ú€Hîº#ÉèŽð >¶€I:$(Ý >²€I $!( AN€IJ#ÜH; ?2€IJ#õ¨ð A2€IÚ#èH ?d€Hóê#öˆY B¬€Iº$QÈ’€ ED€Iê$ HG =@€Iª#Ûh ? €Hû‚#éhÊ @j€Iš$ è1 >΀Hô"#ÜHà ?΀HýÒ$HJ 9è€Há’$¹ @"€Hô#ó¨a ?f€I$kH] Z€I$ (ö ?L€Hüò#ôHŽI 7&€Håª$/(v BH€I *$%¨y 6Š€HéÊ#ûŽˆ C€Hõú#Ûh, @Š€Iº#ýh` >Þ€HüÒ#åh– @€I¢#üHÄ @t€Iª$è ?n€H÷:#ɨ‘. Mh€I)B$"ˆ’­ H&€Hü$6¨  >€Hè2#·hÚ >Ž€Hú’#ØÈŽÜ ?h€I"$)(C ?è€I"$ˆ: @ €Hú$H  >¤€Hüb$¨K B €I*#ᨎ栀Iâ% (”< IÆ€I#R#ÚÈe B”€I $M >Ú€HýÒ$8 ;Ž€H÷*$H‘  FŠ€I "$&ȸ AÔ€IÒ#öh7 A0€Hûâ#ñ(b C4€I ²$#¨â <Ø€HðŠ%Xè’½ C€Hë"$8È7 A˜€Hþb$O(‘¶ >ê€I:$"h' B^€Hîz#ÊŽú ? €I2$Fh‘" ?Ž€Hý‚$(Û >Ü€IZ$*ˆä >€IÚ$%¨k AH€IÊ$ˆÑ /‚€IQš#éh> ?*€Hýâ$ˆ‘( B€Ir$©‘£ ? €Hÿj#åˆÞ ?0€H÷#Û(¸ AN€Iº$ ¨  <~€Hû#òH~ @ˆ€Iò$%$ A´€I²#þ(ô A€Ij$Hü %8€HåB$ÿ¨Q >d€Hü"$xhë AØ€HùŠ#ñh‘© F¨€Iú$ÈÒ ?ø€Hô2#ïè  B€I *$© ?Æ€IÚ$"ˆx Bx€I J$èW BÚ€I J$èH B€I "$6¨– D€HJ$,‘B CF€IJ#ȨÈ >h€Hýr#å@ Cb€I#ühŽþ ?0€I$Ä A €I‚#ëh_ ?f€I$&£ D¸€I*$ˆ A„€I º$¨q Cf€I $Q(‘k F€IR$d‘• 7Ä€I3Š$…È’ O4€I š#’HT CŠ€Hú²#ÅHŽ­ ?€Hèj#º¨ CH€Iò#óˆô =Ô€HõZ#ø¨ @f€Hü $¨¦ B\€Iš$ˆ† A*€Ij$"hâ CÖ€IÚ$Jˆ‘/ D¦€I ‚$$H“2 E‚€I&:$[h‘^ P0€IÂ$~‘> >@€Hîr#Ú¨· >À€I$èÀ Bþ€Hÿª#ÏHŽ ?d€Hÿê#þ( ?X€Hûj$ ¨¦ BV€I b$&ˆ A&€I2$GèÇ A”€I‚$¨ ?L€Hü#ÅH1 : €HÜB#âˆT <´€I š$J¨S <â€Iâ$èŠ =Ü€HûZ$èæ Aæ€Ij$h¿ A€IÊ$ h4 À€H×ê#´Ž­ <ö€IÒ#áèŽÈ ?‚€I$*ˆ˜ Cú€IÂ$L(‘ CB€I’#îH Bì€Ir$h5 ?P€HùZ#éHР?Þ€Hü2#ˈŽÌ ;Z€Hí#¿h‘æ Dh€Ib#ñh§ @€Iò#·HŒ @p€I "#Îèr @°€Hÿr#æ` ?&€IÒ$:H‘ F€I$1H‘ D8€Iê$\¨ì C€I2$1ÈÚ =ò€Hû"#ùˆÍ =h€Hïb#Çhc >€Hý$\È A$€I â$vè" =Þ€HüÒ#ÈB ?Ö€I ’#õHl B8€Hö2#â¨3 C¦€Hùò$H0 A(€I ò$Eè‘8 EÞ€Iº$JH‘T D6€Iò$ µ CN€I¢#åH+ =4€Hýª$ Èa 9à€I #š(Žæ Br€I²$H‘Ò D^€Iš$'ˆ €Hôj#ÄHL >€Hû2#öHé ?€I"#þˆÞ ?€HúZ#áHs =Æ€H÷r#àˆ“ >²€HüZ#ó¨Á >|€H÷’#ÖHG =2€HõÊ#Ûè >€H÷ú#Û(N HP€Hÿr$?¨î :`€Hçú$]È‘‚ A\€I ò$B¨­ Dì€IZ$ ˆ‘ Bj€Hý$G ;ˆ€Hüê$¨{ ?†€Iú$0hÛ Bž€I$ˆÒ >Ø€HùÊ#àÈx > €HùÂ#íÈÈ ?D€Hý#ñ(¯ >T€Hø#ÝÈ| >&€Hù¢#é¥ >v€Hø¢#Û(E t€I*$¨œ BR€I:$ ˆ ?Ü€Hþ’#öèÏ ?(€Hüò#öˆá ?Œ€Hýò#õhÇ >Ø€Hú¢#ê´ ?"€Hýê#û(ï ?š€Hý*#í¨’ =¨€Hô #ÆH4 H€Ib$?(Ë >8€Ir$ah¿ C†€I$:$EˆÓ B2€I*$R @ò€Iª$hï >B€Høb#íhâ ?œ€Hüê#ðÒ @€Iú$h5 @”€Iê$¨/ A€IÚ$ˆa A€IJ#ù¨à>Ô€Hûj#ðhР?~€Hÿ*$ @r€Iâ$È @:€Ir#ÿˆñ ?x€HüÒ#îhm AŒ€I²#û(É ?j€IR$. @€HÿÚ$h6 @Ü€IJ$¨ @À€Iz$&ˆä D@€I"$-hG ?t€HùZ#ßÈ‘ >ò€HþÊ$h2 A€I $ è, @œ€IÚ$H^ Aò€I Z$*(¬ B €Hñ*#Ó¨’á EP€IÒ#ìH AL€Hùê#íÈ‘q D²€Ir$È: @2€I *$èv AÈ€Iº$È\ @€€HûÂ#Þ(” ?¾€IZ$( @®€Iò$$¨€ Av€I$ˆ] B€I r$Mˆ‘o E\€I$Hä >D€H÷’#äèÈ ?þ€IÂ$(G @ê€IR$H @¢€I:$#hÌ D€I$Rh‘M ?€Iš$'(Z @¾€Ib$ (· ì€Hü²#ùÈ @F€I$í ?^€Hüº#õHô @¶€IR$/è‘ Dø€I*$\ˆ >\€Iª#ÿï ?‚€Hùš#ø(" @¤€IÒ$Ÿ >Ø€I $TÈ‘· Dì€Iš$¨ AÜ€HÿÊ#û ?r€HòÚ#£(Ž <€Hù#ï(© >Ì€Hÿb$ˆp BÀ€I $V¨‘I C~€I $¨W B€I z$!èb @ü€I¢$ˆ @*€Hÿ#óh§ >€HöR#ÔHR =€Høú#òˆ A~€I *$7¨‘ D˜€I$ƒ¨’E H€I$È5 Aü€I2#ëÈÞ @€HúJ#¾hŽŸ ;t€H÷â#þè ?¸€Hý:#÷hù @΀I ’$OH‘ D´€IÒ#ëHU = €HúÊ#ý! A€I¢$hq Al€IŠ#ø <ü€Hð*#¶ŽÆ ; €Hî*#ÃF >(€Hüâ$(J B€I ’$2èâ >*€HôZ#žÈg ;0€Hß"$hó A\€Hó2$(Ž“ Fè€I!ª$ˆÈ’ G¶€Iš$%5 AÆ€IZ#÷Õ @È€I¢#ó(f =`€Hú:$(U AЀI2$ˆG @Ž€Iâ$!Èó D€Iú#鈎ô :Ü€HîJ#ÏÈ“ ?T€Iâ$hv B>€IJ$¨õ >8€Hòz#´ÈŽ— 9Ø€Hæê#Ÿ(Ž ;:€HðZ#Ð耠?€Hÿª$ hj 9p€I$Yè‘í G΀Iê$Dˆ¢ AŽ€Iš$,Èe @p€Iz$+è¡ A¢€I$ˆi Ab€IÂ$*Hè Cä€I ê$ˆ @®€Iâ$èà =€Hî*#¸ =|€Høâ#ìhÝ @x€IR$'¯ BD€Iš#øèx ü€Hø"#Ýè— ? €HüÚ#ïÈ· ?F€I:$¾ C´€Iª$-èc ?ö€Hù¢#ÎèŽí :Ì€HèŠ#œˆŽo :€Hê"#´H =8€HùR#÷(% @L€Hö*#ÿh‘ Dì€I2$HŽÚ 9¬€HùÒ$_h’¥ J€IŠ$"¨Ø ?¢€Ir$3H¢ A®€I $=‘^ G$€I$e(å A„€I2$舠B2€I²$ H  ?ü€I*#ýÈå ?¸€I²$èZ @ЀHÿª#öhï @Ü€I z$<¨‘) D¼€I’$/èh @2€Hû"#Ø( ;b€Hêj#¢ˆŽ‚ :D€Hë"#¸H =l€HùÚ#÷ˆ Fr€Hïò#®¨A I€IJ#MˆŽ„ =€Iª$(ü ?¬€I$\è‘ DP€IÒ#¦(Ž* >”€Ir$£è’ž H.€I*$ˆ4 AÀ€I²$è Af€I R$Uè‘¶ F¢€I"$!(3 @Ò€IÒ$(k Að€IR$È_ @º€Hÿª#ùè Aˆ€I $(hh @‚€HÿÊ$(` C€I"$OH‘9 7Þ€Hæ #«È# ?N€I’#ûH Bº€I ‚$>(‘) ?ö€Hær#ž( E°€I $Œˆ‘õ E\€I:$%è` @¸€Hÿ²$Q BÄ€Iê$I÷ Aú€I$(_ B^€I B$1¨Ü C–€I â$"È) ?@€Hû:#ùèG BD€I b$T¨‘  DØ€Ir$L¨”  Jâ€Iª#Ôh ;.€HîB#ÇHŒ ?2€Høâ#âHç AÊ€Ib$Eˆ$ =Ì€HþÚ$"g B,€I*$Hèû Cª€I Ú$ Èì ?”€I*$ȃ B €I J$ˆB @†€I$-H‘ D €I²$>HΠB^€IÊ#ûH˜ Or€I7Š$€¨‘  A€€Høb#Ý( <ž€HòŠ#ßHv =¬€Hþš$'¨‘ DZ€I$N(÷ >Ò€Hé*#ÉH" A8€I:$&q @‚€Hÿ#ÿ¨A A„€I"$n BŽ€I 2$#š Ct€I$Kó BR€I¢$Qè× ?€IZ$Õh“F I(€I’$e³ A€I $èŽü ð€Ir$ ˆ Fì€I%R$i(Ù 8¸€HçJ#ùH6 ?Ê€I:$3È‘  CZ€I#ù¨È ?€HþZ$‘7 GF€Iò$DN ?°€Hè*#üH‘ E€I $ˆ‘ KX€I*B$]hî B6€Ir#û(S ;€HðB#õH ?¤€I ²$r¨‘» D€HÿR#ÍhÏ B^€Iú$œ Db€IZ$BHN >à€Høò#먠Bž€I2$rÈ‘„ CR€I¢$ˆ] >Þ€I"Ò$þ“  Eü€I ’$7H‘ A¤€Hõ¢#ºÈn ?æ€HýÚ$¨Ö D €I $)(s @\€I$.h­ B¬€I *$G(‘W D €Ib#êÈ‘ ?Z€IÚ$*H‘ ?>€Hí #›èè Jh€I9Ò$©H‘€ D €Iz$NH• ?8€Hø2#õè" @(€I’$¯ >¸€I$ ¨ @R€I $;(ù CŒ€Iò$Qhô @Þ€HúŠ#èÈÿ AP€I#‡¨ŽC ?®€I "$¨(’ E4€I Â$+(³ Aø€Hý#Ú(ñ Bb€Iâ$ ¨k :Ô€Hò2$¨ß =d€HùÒ$¨ë Cä€I¢$Dˆ‘ B®€Hÿr#ߨ’ @€Hê*$h’ IÖ€I Š$Rhw @,€IR#ÿÈŽý <€I :$k¨‘? @0€HíJ#ÈŽÜ >€Hô:#Æh¥ A&€I $*ˆØ CÜ€I :$¨€ <¬€IÚ$«H’û K€I R$2èA A*€Hõ²#œ¨« GÌ€I)’$S  9ø€Håš#ÆÈ“ >&€Hþ:$d @|€I:$,¨¹ @ì€Hù‚#ÄÈ‘á Jú€I4$Û(’• E€Ij$è ;†€I$¯¨’g BЀHô’#¯È- @8€Iâ$4H‘y F2€I B#ÿH: C€I Ò$hw GR€I*r$ºˆ‘ï Dž€Iò$HŽÔ >€IÂ$«h‘Ý AÀ€HùÂ#æè^ Dö€Iª$™H’ø IÖ€Iº$ˆÖ E(€IB$=¨‘ï H€I*$=m <’€Hî²$’: Jn€Iº$1(B A¨€IÂ$|ˆ’ MN€I9j$©(‘e Dì€Iò$‚¨‘E Iø€I,’$Šˆ‘7 ?~€HöÚ$*H’7 Jø€I%b$gˆþ Bp€I B$S‘í J`€I4z$ÌH’3 F8€I ú$±¨”° Tò€I? $v¨Î G”€I5ò$Ìè’ E¬€I $;(ˆ B€Iú$\¨’ J2€I% $iH‘¯ Jˆ€IlZ%³h”ƒ Ir€I+š%!H”m I€I j$$Hæ B¢€Ib$è‹ CÜ€Iº$oH‘ Eœ€Iâ%Åh– Mª€I'Ú%(•R Mb€Iú#ð¨z CD€Iz#ë(é AØ€I ò$;H‘) E€Ib%šˆ• NX€IEJ%s(”Å Eø€H÷z#õˆàBv€HüR#á& BÞ€I Â$"ˆ¼ D4€Iú&T(š gŽ€IwB$ȈÈ <ø€I²$0ˆQ ?€I $1h‘ B€IÂ$(Ÿë –R€J]Â'Ü(–¨ A¶€HíR#éèa A¼€I:$ˆÛ E*€I$ ²€€K2*+8ˆžå KÞ€Hèj#Í(< @Ê€IŠ$4è‘2 E^€Ij$>¨~ Î,€KDj*h˜Ù ?ò€Híb$Hj @0€I *$T‘W Dn€IŠ$H(©¨ ˜€IÁB$Þhû @x€IR$ H= CÒ€I²$-¨– D8€I6$Á¨’” GÜ€I $ÈÛ ?â€I *$8o @L€I’ ‡Œ <\€Iº$:èK €IZ$d(Žý <€Hå²#žh® Dà€HöB#º¨Ž0 ;€I"$‹(Žm 8¬€H÷š$aHõ 9ì€IB#y¨* @ ¥7i[n“³È³j’³h“€³(ƒ-s0‡¯§âÊu)ÆÚtf³zø}¬gB–k¦¦BD]³zø},':’j¦F*:[!eS2‡¯‡ÒÂs¨æ¢^a£Eš RžÄÑÐHÂÙ@.¯gÒÀs(ÆšZ`¢å‚Q$©ÄEÄ ˜<’™.*"±4,/GÒ¼r¨†’V_¢…rO¤‰ºCáˆ9—CYd2¢Q%‘âi"'’b‰*)’⪸r(FŠP_"%iúNDq²Ac¹|6–c)T.”b¹8)Âi b !¢ "â1$bQ&âq"(+G"€h$ÅêUŸDÙÎFÃùŽ9—#IZ/”b¹6(’‚Y#âáàøaÐöAÐôAÐöaØø¡àüáñ b "â1$‘‚Z´r§ÆzJ^!…QîLœ„Q¤>˜cj2•Ù<)‚Y"¢þAÀ쎠æŽA˜äŽA˜äŽa è¨êá¸òAØøáù ‚! #+ÇR~h¤…âTž¤ÁÂD™ãÙ~7#H,"q#Áøü¨äÁpÖA`Ô A`Ô ahÖ pÚá€àA˜èŽÁ¸òaàü" "(†²J_!eIæK›Ä9˜<—ƒYZ/”©*%‘B! âaXÌ 0Ä A0Ä A0ÆŒ@ÊŒÁPÐ!`ÖÁxàa ì!Ðøáúœo%†VdÁºCC¹r5Bé:)"A °èPÊ º‹a¶‹a¶ º ÁÀ !(Æ ¡@Î A`ÚŽèŽáÀö«g2ne¢…‰ìM›¤9’;–ãAP-“""Aàðá`Ð ¶ àØª €Ð¨  Ðª ŠÀà°‹ ø¶ ¾Œ!(ÈPÖáˆæÁ¸ô2hŠÐw¨fš>\ÅÂE#Ál4ÂÑ.'BüŽ€ØŒºŠàȤ аž ‰À¨œ ‰à°  Š À¤ Š€Ø¬ ð¸ áÆ áHÔÁ€äŽÁ»DŽ®§Úœn%fSyš=–ÃIH-¢i ¸â !0 @Ц à˜˜‰@€’ €’ ˆ– ‰€ œ À¦ ŠÀà´‹ÁÄŒÁHÔ Á€äŽÁ»b•0h:¶s&ÆJ&WD©¨?—CaJ-’‚a A¨Þ Á ¾ŠàÀ¢ ‰`€ÀhŠ€X†ˆ``ŠˆÀx‰`˜œ Š Àª ‹ ðº A(ÌAhÞa£è²8)Ó$‰¬çŠ‚i£¥¹øN›¤)‚8Bñ,'¢ð¡XÈ‹€àª À€ˆ€P„ˆ @~à@~H‚ˆ€hŒ‰ ˜ ¸ª ‹ ðº A0Îahàޤ »:JSB‘.‡êšn¥&Rœäi”;–#6(‘ðaPÄ @Ф `pŠ 8~ (x‡€(x‡€0|ˆH„ˆ p‰€   Š Ø²‹ÁÆ áPØ!ˆæ–£I<+"(ì ÁH²‰à°Œà@v p‡nàp‡ t‡` z‡à@†Àp”‰à ¦ àØ¶ŒÊAXÞŽ˜ìŽ¡ ð1ú¼}'&Ò.^Ÿ¸E˜c©V1¢   à” ˆ@`z@ rn‡p‡ t‡` z‡à8„Àh”  ˜¢  Ð²‹ÁÄŒáHØŽ!ˆî!¸ðaÂî‰)ç‚Vh!E¡ÚMD!r7”bá%aàÖ ¡¢ ‰ˆ‚‡ 0t pr‡ t‡` z‡à8„À`’‰   Š€À° ÂŒÁ8ÖŽxêAÀúáÚЃ¨G2>d aÆJ#ñb5b¹#ŽÁÀ΋Až àˆ‚‡ 8v r‡ t‡`x (€ˆ`PŒ @x𠍍 àØ¶ŒÊ APÞ˜ôáØÄ ¡3+gòlo"¦ ìSDq€<•#)**b ä P²‰à¸ˆ@`|€(v` v€ z‡À0‚€P‰`€ž @¨¦ Š À® Ø´‹€ø¼Œ!Æ ¡0Ð APÚ ápêA°úáÑñ À  Š  ¦  ¸¬ ‹Ð´ `躋áÂŒ Ì @Ö ¡`àa€ðA°úÙ¡ñ Bê‹)ǪVk!eÑÚPDIt:”ƒ"(â H´Š ¸” €p€À8z 0|à8€`HŒ‰h” €xœŠ¢ `¨ª ŠÀÀ° ‹ ض  ð¾ !ÆŒ¡(Î!HØÁhâŽaˆì¨öÁÉaé ‘ !‘¢(‚ H„ˆ`PˆÀX‰@p˜‰À€ž ˜¦ Š °¬ È´ `຋àøÀ AÈ Á0ÐaHÚáh䎈î!¨øÁÉaé ‘" !‘Â) #­Hjˆv¤FzZÄÙšCÙD0!A¨Ì ¦  ¨ˆ€p„ˆ@P„@P†`Pˆˆ XŒ h” €xœ ¢ Š`¨ª ะ ‹@и ‹ è¾ !ÄŒÌ0Ô PÜpæ¡îA¨øáÑé‘" !‘Â)"#’bI,%ˆ `Š `Œàh‰ p”‰€€œФ Š€¨¬ า ‹@и ‹Àè¾ !ÆŒÌ 0ÔHÜŽ`ä€ì! ö¡ÁAá â!‚!#"A($’ÂY2&±)Jƒ'§:8eŸÅ‰ÆMd1j9”C "(B ê!`¾ 𢠉 °” ‰€‰x‰x’‰ x”‰`€š‰à  Š@ ¨ ŠÀ°° @ȶ  à¼ŒðÄ aÊ Á ÐA8Ø ÁPÞAhèŽÁˆðA¨øÁÁaá !¢!#BA(%âa2'‚x𠉀 ˜ ‰`– `ˆ˜‰€ˆš Àž Š  ¦ Š °® ‹À´ €Ø¼ àèÂŒAÈŒ¡Î !(Ô@ÜXâŽapêáòa¨úÉé ‘" !‘¢) #’BA*%âa4'‚<)0I*¸‚''22e…‰ÂM™$1j:c&*¢0𠡀ȋ¡°ŠÀè¨ Š@Т ¸ž ਞ ‰à ž  ¢ Š@¨¨  ¸® ȶ €à¼ŒðÂŒaÈŒÁÎ !(Ö@ÜXäŽapêáˆòa¨úáÁaá áù ‘‚"’9&$’¢Y0&“By8(â‘B*‚°¼‹a² 𬊠ب `Ȧ @¸¤ Š`¸¦ Š À¬ Ȳ `غ àðÀŒAÆŒ¡Ì(Ô a8ÚÁPàŽAhè¡€î!˜ö¡°þ!Éé‘!¢!#"A&%ÂY0&“By:(“â™D*”‚±L,/É2°‚¦§2*eŸ‘¼NAj;£),+‘HøA¨Ô áXÈŒA8À‹Á¸‹A² è® Àج ÀЬ àа ‹@ظ  è¾Œ!Čʌá ÐA8Ø ¡HÞ`äŽxìáˆòa úá¹AÙÁñ B !‘Â) #’BA(%Âa2'b:(”™D*”‚¹N,•"ÐìA¨Ü axÐ ÁPÈ A0À Áº‹¶‹@𲋠贋`è¸ ÀøÀ !Æ ¡Ì (Ò a8Ø ÁPÞŽ!`æxìôa¨úáÁaÙÁñ‘B !¢!#"A&$’¢Y.&“By8(‘@*b±J,âÉT-•‚é\/4*Zð“*h*`s¢&YêY„éEÁR4“BÑ'b üAàìa¨à ¡€ÖXÌ @Æ !(À‹Á¼‹¡º Á¾ Ä Ê á(Ð A8Ö ¡HÜŽ`âŽapêÁˆðA øÁ¸þ!É¡á ù ‘‚"â)"#’bI*%âa2'by:(“â™B*”b±L,ÑT.‚é^/–# X5ƒ:.â±"(ba#BüaàðŽ¡°äáˆÚahÒŒáHÊ 0ÄŒA  AÄŒa ÊŒÁ(Ð !8Ö HÜ á`âŽAp莡€î!˜ö°üÉaÙ áñ B !Â!"’"9&$¢Q,%“i4'“‚<)¡D+‚¹L,•"ÙV.¢ñ^0Ch1–Ã+6¥®i:œ‚¥§:fž¥¡¾O™¤iŠBÃál:ÃaN2”ù4,’¢¡ '‘bY#b ¡èôá¸èŽAÞ ¡pÖ!XÐ áHÌ Á8ÌŒá8Ð !@ÖPÜá`àŽAp掀ì˜òa¨úáÁAÙÁé‘"!¢"1$#’bAÂP›$Á¢G™$1‚?#±d7•cAH1Âá2+’¢™ '‘‚Y#¢! áðø!Àì ä€ÜhÖ aXÖaXØ¡XÜ áhâAx掀ìŽá˜òA¨øÁÀþ!ѡ醹²êbà”)¨:\u"&‚ b%ÁÞVœ¥ºM¤‰˜D˜¤z<–£‘\5•#)F0ÂÙ4+’¢™"'‘ÂY$â! !øüaÐòÁ°êa⎀àŽxàŽ!xäŽa€èŽ¡ˆìá˜òA¨ö¡¸üÑêBo"f’c…ÑæXE1ÂN$™ E™‚=—C©f7£IP2‚ù>-“b¹.)’by &¢I" ðüaÈô°îŽÁ êŽ¡˜êŽÁ˜îŽá ðA¨ö¸úÁÉ!Û€º2Êrà•©èZbv¤g.j!fB^žå‘ÜTÄùºK¤q˜C£ù|<‘f6•ÃAR1”¢ùB-“¢¹2)’Â$&‘âI#‘! !aùáàúÈöa¸öa¸öÀø¡ÈüáÑAâ„~¦gzLq#F² e ÅùøZžeYÔQ$ɲH$I’Acáz;‰f6ã9V1”ÂùF-“âÁ6*â‰('"Y$b1" aù!éáá!áaé.irÄ*hrˆ¦ÇŠTr£æÂ*f¡f[ŸqÜR¤ÙºIš¤aœB™$†=ér8ƒa`3•ƒP0‚á@,¢©2)Ây&&"Q$‚1"‘"!â  Â Â ÂÊ*¨‚€§g¢^s¤†Ú4h"* ]…æSDùÂK›D¨EÄ!’?ƒÉ~:—Cl6CAZ2CL.”BÉ>+‚¡2(’ây(&’BY"$’A#‘¢1#‚)"‘b*²‰)ˆ~{&‡JRo#æ’*d!eêYžåQÞQäÙÀJDq¨Dä”?£É€:ƒn6cA^2ƒ P/¢ÙD,±:)“b‰2'’âq,&’¢a(%’bQ$%"J ƒ(‡Êrv%ÇHj£&R` ¥¹øW…1ØOœÄÁÀIDiªCš–?ÃÉ„:—£r6–£Id3ÃV/•"éL-bÁB+â¡<)“‚‘6(“B2'©GÚ|w¦gRl#Æj(b!EÒY%QäQ„éÌKœ$‘¶FÄ9¢Aƒñ<˜c©~8—cqp5£9d2ãX/•BéP-”ÂÉH,b¹D+(g’ps%¦ÚFh£&: _ å²WŸ%AæQ¤áÎKD‰¸Fä9¤AÃñ’=£±‚9Ãyv6Il3c!b1ãZ/•béT.)ªzt¦FòPj£Æb*a¡¥Ú ZåiòSže ÜM±ÆH¤Y°Cš„ž?cÙ;˜ƒ¡‚8—ãqx5—CIp3–Ã)h2C„v¦çZl¤†‚6d"†\ Å’VE1èPÄÑÒJœd¼E›D9ªAš#ùœ>cÉ;£™†8˜#q~6£ZŽx'§:fn¥FªDf£F*&_!¥º X YôRž¤ùÞMD©ÊHa¸D!ª@š#ñž=™ƒÁ”;¡Š9)‡ª„u§'`m%’Be#F&^!¥²X %QöR¤ùàMd©ÌHœDi¾Ed1°AšÄ¦?#Ùž<©‚~s¦æú^k¥‚Bd£F&]¡¥ªW %IöQžÄùâM¤±ÒI¤yÄFäAºCD°@)ǪŒv'Ç*ln¥æªNg$&:4`"eÒZ årTŸ…!ðOždÙàL„¡ÒHœÄqÈEœ$Bª})‡’Šu'§jm¥ÆšNf$&*4_¢…ÊY¡rTŸÅ)ôPžÄéæM¹ÚIdЏª‡º–w¨‡Bxp&¦Ê\h¤æR@b#Eò(\!ÅšW ¥RS¥ôOžäáèL¬h*´~ªGª”v¨g*vo&†²Zh$ÆJ@a£Eê*\"¢X!b T %)üQ-HRÂ+'Ò¢y)'R‚q§FÚfj%¦rLd$&6_"åÊ&Z¡å’W!%Zàˆ-:¾ªçºžw©B€p'&Òfi¥¦jNd$F:_£%Ú,[¢e¢îŠ­ÈbÊ‚+§âªz)ÇjŽr¨òrl&f’Zf¥&JHb$& :^¯¨Ò舭ˆJÈ€«‡Ê¨y)§RŒr(òtl&†š`g%fRPc0ˆúö‹®HzÔƒ¬gú¶{ªg‚št¨Ç€n§fÊnj&fƒ’°HâòŠ.(bÒ‚,Gâ´zª‡zšt©†o§æÓ‘0Òðˆ®RÐ,'Ú¶z*§ržt©g*Œp² ;¯èºî‡®BÒ€¬GÒºzªç‚¦u±é+ޝèªî†®:Ô€¬§Ú¾{1É ¯è¢ð†®H:Ú€²©K°èÓ‰¯hjê„2É;1(ÓŠ3És.“²) Lš4 sRš L €@$@@ €@ @@  @@ @@$@ A€@À 0@  @€@$@@€0FÀä0 CÀd0 @$@€@  BÀdp9 €Ä`0 „@„@ „@! €D C‘Àà`1 €À` „@!„@!€@ D‚Q ”X,A€ B€D  G€À`0„@!„@!€@ D H$ ‚A X,A€€ €D B€D0 €€@!D€@!D„@!€H% D‚A H$ ‚A`° €@ B€D À`` „@ D„@!€@! D‚A H$ ‚Q ”H$ ‚À`4:€D0 B€D €P(€@!D„@ €H$ ‚Q ”H% D‚A ”H% ‚A P)‡Â¡@€@ BÀ`   €@!„@  H$ D‚A H$ ‚Q H$ D€@! Aøx(€@ A€„@ €@!‚Q ”H$ D‚A H$ D‚Q H%D„@!„P(Bá@ P € €@ D ”H% D‚A ”H$ D‚Q H%D€@!„@ @¤ P T(€D@@ „H% ‚Q H$ D‚A H% €@ „@!„@ „P(РP(€@ @ P) D‚A H$ D‚A H$ ‚A„@ „@!€@ „@ €@  @ BP B P8 €Q`°H$ D‚Q H% D€@!€@!€@ €@ D€@!D@ P(E@ ( €P 8P T‚Á H$€@ D„@!D€@ „@ „@!„@ ‘@¤ A€à4 €@ ( B@D„@ €@ €@!„@ €@ €@!€@  A‘@¤ŽG@€P €D @ @ €@!„@ „@ „@ „@ „@!„P)E€@  @€P€D E‘€@ €@!€@!ˆD"„@ D€@!„@ €@!D@  `0B€D  D„@ „@!„B!ˆ„@ „@ D„@ „@!E€@  €P  C€„@ D€@!€@!D€@!„@ €@ €@ D€P(D@ €@ @€@ F€@!D€@!€@ €@ D€@ €@ €@ D„@!D€@ @ P(D€@!D€@ „@!D„@ D„@!D€@ @ @ B€À`0D„@ €@!D„@!„@!D€@!D„@ €@!D„@ €@!D„@!€P( A€@ €@ €@!D€@ „@!€@ D„@!€@ €@ €@  E@$@€@ @ €À`!D„@ D€@ €@ €@ „@!€@ „@ €@ D„@ €@ €@ €P) E€@ @ D„@!D„@!D„@!D„@!€@ D„@!€@ €@ €@ €@ @¤P(€Ð`0 p9 €„@ D€@ „@!„@!„@!D„@ D„@!€@!D„@!€@ „@ €@ €@ E‘@¤ D€@ D€@ „@ „@!D€@ D„@ „@!D„@ €@ D„@!€@ A@ @€P@  ‘Àà`0 „@ „@ €@ €@!D€@ „@ „@!D€@ „@!D€@ €@!D@$ A€@!€@ €@ D€@ „@ „@!€@ D„@ €@ „@!€@€@ @@€@À`p9„@ D„@ „@ „@!„@!D€@!D„@ „@!D€@ „@!@@@€@  CÀàp)D„@!D€@!D€@ D€@ „@ €@!D€@ „@!D@@€À  €P € BÀ`0E€@ €@ €@ „@ „@!€@ D€@ „@!@@€@ A@$ A@ €À 0 @€D B€@0E‘@ @ €@ €@ „@ „@!€@!D€@ @@ €@  A@$€@ @$ A@$0 €À`0@€@ @@$ B€@ B€D0 E@ @!D€@!D€@ D„@ „@!„@!@€@ €@ €@  @€P € €D € @¤@!„@!D€@!D€@ D„@! A@$@ €P €@`0€@ €@ @ @ „@ „@!€@!D@ €@$ €@ @B€@ B€@ @@  ‘€@ „@ €@ @$€@$@ @€@`4 @ €D B€D@@   D€@!D€@ @¤@@€@`0 @€@ B€@ @E‘@ @ D„@ @$ A€@   €P € €@ €@$  „@!E€@ A€@ A€Ð`0@€PB€D B€@ €@ P( @  @  ƒ@€@ @@ €D B€@ @A@ P(H$ €@ @€@ @€@@B€@ €@ @@@$A H$‚€ €@ @ B€@ €D@ A  ‚€@  €@ €D €D €€@$ ‚A @€@ @@B€@ B€@ @  @€P €D B€@  A€@ @€@ €@ € B€@ C€À  @ @€@ @ B€@ €Àd €P €P € €@0 A€@€@ B€D  €@ €@ @€@B€D  C€@ €@ €@€@0 A@$ @€@ €Àd @ÀP €P À 0AàÐ8@€@ @ 0 ‚Áàð8€@ €@$ ƒ@àP €@ A`x4@€@ X$ @€P @€Px4 @€@ @AàÐ`4 €@ €@  @€@ @@$ €@ A€Ð`0A€Ð@  €Ð`0 €À`4 7777BUFR4b€Ë4Ë~hd!]ò}L!Øb¿°V@Ü à.ÿÿdE¤F àÀÌFÔ €(!I¹¾@ € €@À À@À`À!Aa¡@!@A@a@@¡@Á€!€A€a€€¡€Á€áÀAÀaÀÀ¡ÀÁÀáÁÁ!ÄaÄ‚Bb‚¢Ââ"Bb"Bb‚¢@B@b@‚@¢@Â@âAA"ABAbA‚A¢CâDD"DBDbD‚D¢€b€‚€¢€Â€â"Bb‚¢Â₃‚ƒ¢ƒÂƒâ„„"„B„b„‚„¢ÀbÀ‚À¢ÀÂÀâÁÁ"ÁBÁbÁ‚Á¢ÁÂÁâÂÂ"ÂBÂb‚¢ÂÂÂâÃÃ"ÃBÃbÂâÃÂÃâÄÄ"ÄBÄbĂģcƒ£Ãã#Ccƒ£Ãã#Ccƒ£Ãã#Ccƒ£Ãã#Ccƒ£Ã@ƒ@£@Ã@ãAA#ACAcAƒA£AÃAãBB#BCBcBƒB£BÃBãCC#CCCcCƒC£CÃCãDD#DCDcDƒD£DÀƒ€£€Ã€ã#Ccƒ£Ãã‚‚#‚C‚c‚ƒ‚£‚Âッ#ƒCƒcƒƒƒ£ƒÃƒã„„#„C„c„ƒ„£„ÃÀƒÀ£ÀÃÀãÁÁ#ÁCÁcÁƒÁ£ÁÃÁãÂÂ#ÂCÂcģÂÃÂãÃÃ#ÃCÃcÃãÃÃÃãÄÄ#ÄCÄcăģÄÃÄ䄤Ää$Dd„¤Ää$Dd„¤Ää$Dd„¤Ää$Dd„¤Ää@„@¤@Ä@äAA$ADAdA„A¤AÄAäBB$BDBdB„B¤BÄBäCC$CDCdC„C¤CÄCäDD$DDDdD„D¤DÄDä€d€„€¤€Ä€ä$Dd„¤Ää‚‚$‚D‚d‚„‚¤‚Ă䃃$ƒDƒdƒ„ƒ¤ƒÄƒä„„$„D„d„„„¤„Ä„ä…ÀdÀ„À¤ÀÄÀäÁÁ$ÁDÁdÁ„Á¤ÁÄÁäÂÂ$ÂDÂd„¤ÂÄÂäÃÃ$ÃDÃdÄäÃÄÃäÄÄ$ÄDÄdĄĤÄÄÄäÅEe…¥Åå%Ee…¥Åå%Ee…¥Åå%Ee…¥Åå%Ee…¥Åå%@E@e@…@¥@Å@åAA%AEAeA…A¥AÅAåBB%BEBeB…B¥BÅBåCC%CECeC…C¥CÅCåDD%DEDeD…D¥DÅDåEE%EEeE€e€…€¥€Å€å%Ee…¥Åå‚‚%‚E‚e‚…‚¥‚ł僃%ƒEƒeƒ…ƒ¥ƒÅƒå„„%„E„e„…„¥„ń充%…E…U¥E¥U¥eÀ…À¥ÀÅÀåÁÁ%ÁEÁeÁ…Á¥ÁÅÁåÂÂ%ÂEÂeÂ…Â¥ÂÅÂåÃÃ%ÃEÃeÃ…Ã¥ÃÅÃåÄÄ%ÄEÄeÄ…Ä¥ÄÅÄåÅÅ%ÅEÅUÅeÅuåeåv¦Ææ&Ff†¦Ææ&Ff†¦Ææ&Ff†¦Ææ&Ff†¦Ææ&Ffv†%v%†%–@Æ@æAA&AFAfA†A¦AÆAæBB&BFBfB†B¦BÆBæCC&CFCfC†C¦CÆCæDD&DFDfD†D¦DÆDæEE&EFEfE†E–E¦e–e¦e¶€æ&Ff†¦Ææ‚‚&‚F‚f‚†‚¦‚Ƃ惃&ƒFƒfƒ†ƒ¦ƒÆƒæ„„&„F„f„†„¦„Ƅ慅&…F…f…†…¦…¶¥¶¥ÆÁÁ&ÁFÁfÁ†Á¦ÁÆÁæÂÂ&ÂFÂfÂ†Â¦ÂÆÂæÃÃ&ÃFÃfÃ†Ã¦ÃÆÃæÄÄ&ÄFÄfĆĦįĿÅÅ&ÅFÅfņŦůÅÖåÖåç'Gg‡§Çç'Gg‡§Çç'Gg‡§Çç'Gg‡§Çç'Gg‡§Çç÷&A'AGAgA‡A§AÇAçBB'BGBgB‡B§BÇBçCC'CGCgC‡C§CÇCçDD'DGDgD‡D§DÇDçEE'EGEgE‡E§EÇEçFeWegGg‡§Çç‚‚'‚G‚g‚‡‚§‚ǂ烃'ƒGƒgƒ‡ƒ§ƒÇƒç„„'„G„g„‡„§„DŽׄç„÷………'…7…G…W…g…w…‡…—…§…Ç…ç…÷†††'†7†G¤—¤§¤·¤Ç¤×¤ç¤÷¥¥¥'¥7¥G¥W¥g¥w¥‡¥—¥§¥·¥×¥ç¥÷¦¦¦'¦7¦G¦WÁGÁgÁ‡Á§ÁÇÁçÂÂ'ÂGÂg‡§ÂÇÂçÃÃ'ÃGÃgÇçÃÇÃçÄÄ'ÄGÄWÄgÄwćėħķÄÇÄ×ÄçÄ÷ÅÅÅ'Å7ÅGÅWÅgÅwŇŗŧŷÅÇÅ×ÅçÅ÷ÆÆÆ'Æ7ÆGÆWÆgãçã÷äää'ä7äGäWägäwä‡ä—ä§ä·äÇä×äçä÷ååå'å7åGåWågåwå‡å—å§å·åÇå×åçå÷æææ'æ7æGæWægæxhˆ¨Èè(Hhˆ¨Èè(Hhˆ¨ÈØèø(8HXhxˆ˜¨¸ÈØèø(8HXhxˆ˜¨¸ÈØèø(8HXhxˆ#È#Ø#è#ø$$$($8$H$X$h$x$ˆ$˜$¨$¸$È$Ø$è$ø%%%(%8%H%X%h%x%ˆ%˜%¨%¸%È%Ø%è%ø&&&(&8&H&X&h&x&ˆ&˜AˆA¨AÈAèBB(BHBhBˆB¨BÈBèCC(CHChCˆC¨C¸CÈCØCèCøDDD(D8DHDXDhDxDˆD˜D¨D¸DÈDØDèDøEEE(E8EHEXEhExEˆE˜E¨E¸EÈEØEèEøFFF(F8FHFXFhFxFˆF˜F¨F¸c˜c¨c¸cÈcØcècøddd(d8dHdXdhdxdˆd˜d¨d¸dÈdØdèdøeee(e8eHeXehexeˆe˜e¨e¸eÈeØeèeøfff(f8fHfXfhfxfˆf˜f¨f¸fȈ¨Èè‚‚(‚H‚h‚ˆ‚¨‚Ȃ胃(ƒHƒhƒxƒˆƒ˜ƒ¨ƒ¸ƒÈƒØƒèƒø„„„(„8„H„X„h„x„ˆ„˜„¨„¸„È„Ø„è„ø………(…8…H…X…h…x…ˆ…˜…¨…¸…È…Ø…è…ø†††(†8†H†X†h†x†ˆ†˜†¨†¸†È†Ø£h£x£ˆ£˜£¨£¸£È£Ø£è£ø¤¤¤(¤8¤H¤X¤h¤x¤ˆ¤˜¤¨¤¸¤È¤Ø¤è¤ø¥¥¥(¥8¥H¥X¥h¥x¥ˆ¥˜¥¨¥¸¥È¥Ø¥è¥ø¦¦¦(¦8¦H¦X¦h¦x¦ˆ¦˜¦¨¦¸¦È¦Ø¦è¦øÁ¨ÁÈÁèÂÂ(ÂHÂhˆ¨ÂÈÂèÃÃ(ÃHÃXÃhÃxÈØèøÃÈÃØÃèÃøÄÄÄ(Ä8ÄHÄXÄhÄxĈĘĨĸÄÈÄØÄèÄøÅÅÅ(Å8ÅHÅXÅhÅxňŘŨŸÅÈÅØÅèÅøÆÆÆ(Æ8ÆHÆXÆhÆxƈƘƨƸÆÈÆØÆèÆøÇã8ãHãXãhãxãˆã˜ã¨ã¸ãÈãØãèãøäää(ä8äHäXähäxäˆä˜ä¨ä¸äÈäØäèäøååå(å8åHåXåhåxåˆå˜å¨å¸åÈåØåèåøæææ(æ8æHæXæhæxæˆæ˜æ¨æ¸æÈæØæèæøçç©Éé )Ii‰©Éé )9IYiy‰™©¹ÉÙéù )9IYiy‰™©¹ÉÙéù )9IYiy‰™©¹ÉÙéù )9IYiy‰™©¹ÉÙéù )9"Ù"é"ù# ##)#9#I#Y#i#y#‰#™#©#¹#É#Ù#é#ù$ $$)$9$I$Y$i$y$‰$™$©$¹$É$Ù$é$ù% %%)%9%I%Y%i%y%‰%™%©%¹%É%Ù%é%ù& &&)&9&I&Y&i&y&‰&™&©&¹&É&Ù&é&ù' '')'9'IAÉAéB B)BIBiB‰B©B¹BÉBÙBéBùC CC)C9CICYCiCyC‰C™C©C¹CÉCÙCéCùD DD)D9DIDYDiDyD‰D™D©D¹DÉDÙDéDùE EE)E9EIEYEiEyE‰E™E©E¹EÉEÙEéEùF Fb™b©b¹bÉbÙbébùc cc)c9cIcYcicyc‰c™c©c¹cÉcÙcécùd dd)d9dIdYdidyd‰d™d©d¹dÉdÙdédùe ee)e9eIeYeieye‰e™e©Éé‚ ‚)‚I‚i‚y‚‰‚™‚©‚¹‚ɂقé‚ùƒ ƒƒ)ƒ9ƒIƒYƒiƒyƒ‰ƒ™ƒ©ƒ¹ƒÉƒÙƒéƒù„ „„)„9„I„Y„i„y„‰„™„©„¹„Ʉلé„ù… ……)…9…I…Y…i¢i¢y¢‰¢™¢©¢¹¢É¢Ù¢é¢ù£ ££)£9£I£Y£i£y£‰£™£©£¹£É£Ù£é£ù¤ ¤¤)¤9¤I¤Y¤i¤y¤‰¤™¤©¤¹¤É¤Ù¤é¤ù¥ ¥¥)¥9¥IÁé Â)ÂIÂiÂy‰™©¹ÂÉÂÙÂéÂùà ÃÃ)Ã9ÃIÃYÃiÃyÉÙéùÃÉÃÙÃéÃùÄ ÄÄ)Ä9ÄIÄYÄiÄyĉęĩĹÄÉÄÙÄéÄùÅ ÅÅ)âiâyâ‰â™â©â¹âÉâÙâéâùã ãã)ã9ãIãYãiãyã‰ã™ã©ã¹ãÉãÙãéãùä ää)ä9äIäYäiäyä‰ä™ä©ä¹äÉäÙäéäùå JZjzŠšªºÊÚêú *:JZjzŠšªºÊÚêú *:JZjzŠšªºÊÚêú"z"Š"š"ª"º"Ê"Ú"ê"ú# ##*#:#J#Z#j#z#Š#š#ª#º#Ê#Ú#ê#ú$ $$*$:$J$Z$j$z$Š$š$ª$º$Ê$Ú$êBšBªBºBÊBÚBêBúC CC*C:CJCZCjCzCŠCšCªCºCÊCÚCêCúD DD*D:DJDZDjDzDŠDšDªDºDÊDÚbºbÊbÚbêbúc cc*c:cJcZcjczcŠcšcªcºcÊcÚcêcúd dd*d:dJdZdjdzdŠdšdªdºdʂڂê‚úƒ ƒƒ*ƒ:ƒJƒZƒjƒzƒŠƒšƒªƒºƒÊƒÚƒêƒú„ „„*„:„J„Z„j„z„Š„š„ª„º„Ê¢ê¢ú£ ££*£:£J£Z£j£z£Š£š£ª£º£Ê£Ú£ê£ú¤ ¤¤*¤:¤J¤Z¤j¤z¤Š¤š¤ª¤ºÃ ÃÃ*Ã:ÃJÃZÃjÃzÊÚêúÃÊÃÚÃêÃúÄ ÄÄ*Ä:ÄJÄZÄjÄzĊĚĪĺãã*ã:ãJãZãjãzãŠãšãªãºãÊãÚãêãúä ää*ä:äJäZäjäzäŠäšäªä»;K[k{‹›«»ËÛëû +;K[k{‹›«#K#[#k#{#‹#›#«#»#Ë#Û#ë#û$ $$+$;$K$[$k${$‹$›$«C[CkC{C‹C›C«C»CËCÛCëCûD DD+D;DKD[DkD{D‹D›D«ckc{c‹c›c«c»cËcÛcëcûd dd+d;dKd[dkd{d‹d›d«ƒ{ƒ‹ƒ›ƒ«ƒ»ƒËƒÛƒëƒû„ „„+„;„K„[„k„{„‹„›„«£›£«£»£Ë£Û£ë£û¤ ¤¤+¤;¤K¤[¤k¤{¤‹¤›¤«Ã«Ã»ÃËÃÛÃëÃûÄ ÄÄ+Ä;ÄKÄ[ÄkÄ{ċěīã»ãËãÛãëãûä ää+ä;äKä[äkä{ä‹ä›ä¬ÌÜìü ,<L\l|Œœ¬#Ü#ì#ü$ $$,$<$L$\$l$|$Œ$œ$¬CìCüD DD,DáGŠ ¨èX¨âàmÛÐÅ›†bö4Ê³× ˆsµã¸Õ€û¯HÆBOþ‚b(vÎÖP¨ANÂ@º«cǰ1¢A¨(wšÃó"!Kqâ +¨L¾ââ­Ô¤ì.ÙÁ„H ŽtgØcYЦèãôGU¼<`Aðˆð‚âD28"j()zÁ‚" Ãp{®„Jp%¸AH¶ à_ÆÃ4‚Vpè-‡®@Ø!´æÐ–æ(äÁT  ˜[îbú™­øÌ3—ä6oñÀùŽtwÃÓ3q9MH‚CöpKí‚ÌÌË éf$`Gì‚u°ap¸ž†0Ä4êá–ìP~,'¬"ïÁ%‰”XP‚›I³x´eEÙD0|‘w ÷ìkãtyê‹ÇŠª>!ý«Yð†1 ‰ý)0·jàˆê³„)ác- ò˜fXi úÀõiD ¢;ù¸øœ‘EÖ*‡aÏ z¬_:#ÅXÒ¾Ì 8±Î(ŽÝxzPƒíx D)êÈ}pÁðK–ʵ@è·èGÀÂtRS`¸..4ÕÁœæ}óÄ%ê"á±$‡‰‘8OèB𫍴&Å×P0láú ôkãs4rÐêS‡‰=øýGVІ@n(Jp)f ­zÿ„CÌ%†AGX `_\ƒ10;àçe‡§Ä@œ¢ Ùˆ•‰Dâd(ÅS¿ [¶"ø×Ÿ ˶“ü6RAÀŽm\ṽъeõˆEÆO 0%íÀÏ ±£fH9ûÂøâ œ¤Q¸-ìAŠ¡ ,¨p.÷ÂmQýˆ´„IÂcTó¦UEhö,øuW ìd#<¸ ÜއÀ:†ÑáÉz5¤ì! Ťt×DO‚Ý`Ùø¨ðD‚Vpeà°µ…òD2öᲫnˆz=ÄÖ!ï UN‹^3X°dE¹±û·‚U¤-Ó!Û1>H­|FE8òýÜ‘¤dš¶`˜ÎAZ Ò\ ƒLìÅá # ¸O³þRPÈ †¬48À!àõßH…ÃÄd$Ïq4 |SÀ¢¹Ÿh¸`Þ&/ÈÑ… ^dŸc2ŽÓfƶ\6Œ»Ž8r%ãžÂaàîsÇŽÄ=OQñDÀlµÄ A Æ¡ ¦HhXDò'©søR$xV$/I$ß B'»áD¨Š[,T‹Â±¿ùȳ3´¾.}‘z 4bãÚ[hÎ9ÆŒô5=±°· » oc‰õ¼@éFÇe\<æÝm8}ãöt 9fˆ>ZBÍ’6 ÄŠ¸„cW#‡Q¥‰RIžâSÀcÜ}`ŽßP(1>A¿Ú®Šê„Ã$)w¡f± ¸g2Ão~+0öÓˆ"lDqâ>ƒÍH™Â„é:(!qGÕ t,UP¢¸-X´ÉEÁ .á‘}ÉŒ$˜b×#$3Œ ÏÉÆ™B5£A³ãÕhpZƒgî@êÝqªC3" b‘9`‹€„i°#ºá!;É%JRVí I¼Ký"m|×°¢Å+¢*6AX{ŠùÄYzBÙe6ø½†Ø0÷ñŽp ©Ìfý£E€˜˜Ø#FÜ@7¸ÄŠZ8t„#±´ú8ó0G´¨>~qú° 4‚3!^1bÈŽ/©‘„ Vüdg#0Ìò0ÒöF²t6kAº#Žhqí£œçSÐíöÇŠÜ=0ð=¸8t$ 4 ·É #dpCü²&¯kÄÄvI$©$b >6JÎ]9“ Cn‚)´ÐþÄ£%îñ6A çðPñâ”ðP«ÿEzî,°¡l5‹—”^o t(Æù†Rò3o1¢C Hdkòcm&Õâ Ç+(:2qØPŽøÐyxãÙZ6 ýÈô@øÒªÌ‡ äEò"¹RˆÝºGÈ’E_„”®„³&™3ž¯2(ÐFÀ‚¡pjÞDÉÀE ^@¡@²„ÿð3^µä†Àzÿƒò¾ o! )ˆ‡˜Eèâ<ÚQØ•ó„Ê'-±@ 6ØSi"¨Ã± °íÅ¢b-ìAv çD`æC¬øËô†z˜4­ñ¬ –èni£€às˜æûGS;nâFG¸{ð#íÔqH+hB6’úà‰‰dYÞ#!÷„'(„ž?²"ÖÁf‰!€J¸"cT‡8Ÿ˜E„)“ÁSgŠÑ$X5BÏ$帺’…ïˆ0RQ‰\ €Èe¸£;?FÕŒÆÇZ7¿iŽ1˜s<§s¦ ð™ÇŸÂ=×Aõƒâ€Â„§! Ñ ³HxÀD¢R+Ü•Ž^䀊$ry&þÉSKrbsJHœ¤íÑ'ܱBJBVÀÀ´Ï…Ü0’a‘ô ü8k:tö}Àꞇ‹@>!ýÄY(†.L2#:Á †‰:€K€"i{¸p¡"$6)ùQV{ éÀYbÕdð¼EûÖ0·áŒ| š,f}ƒAfwÈ×#Ô 7y‘Â}IÐtã­šÙhò)Ǭt>9±ø—ú ‡dÎ!; =…rEÂ.ü®,*†ã$¤y(ˆ‰_ÎK×¢e“bäœÏÄô*( éCà€ÅDÙ`LEÍ”Ë éM xGÀÂY,Ÿp£ÅS¬,Ioß êb´Ã0h\pÙ”ì9ÃÛ}G¸}¢„Ö!áoˆ±ÈG:bGf¦8˜–„ߨ'ÓQEWŠaT·‚³O€³Š…·z.“q{L Hb4£8e΄ÆL5R±YÁo¸‹SŠ鋇g‚<±çgq„}>ƒ÷n (B B/ÄT0™kÜ)¹A[+ D`]‡Ã0Ï:¯¸70!Æâ¢xuƒÞnÌ¡ˆ^øD£â2²˜“i„¶&ˆ:ýŠ8R!ži_®]…à-Epò ½x_ž# k¾`ÉWÆe²4Á¦ó mämCvT8ä^‡>Dp7‚(¼ž ¿åÖÈ:ëš2àˆ`„xˆ%pa9 3¸U‚¤îP¾#'d2çA¤Í ‘poãÚD¨0ô ÕÜ@aBkïðŠ×Äq€$e1)Ú …MØ"|"Là¥ËÅI +#Á_΋4\[UBè$¬(ÀÆ!$1âQ•ÏŒähÒcT  4îÂ2ç ~„%¸"à!$I ŽàOÏB™ £³ÉÔ”0PÁ ëÐj¶ÃpÜ\ð鱃 =Äû·Iˆ…¤„HJ#aŒ‰1èKA¢gn¨ žÅ¸)ÕaUtŠáŒX¸‚Ó>ˆ»’Å÷¼0“ñ‹\Œ‘0f8Ã?Y8îÁ-^ f2ƒgàèôÓ CñÂ:P¨œô*[Á`q n^ÙCŒbpÑÝÄl7ÕÁËöÌHyºƒèú ḈsHEFb7Æ)8”®„Àh&ÙQ=‡Š"ˆR£}‡¸¯¢…˜-–Qs| ÑÈ`@£ç1JÁ¥|ðvÀìL!Õ @L2B|T»Ð¬šÄ.!Œ whg SÂt âj‡HØ;ù!í*ÔX‚„*þ"1!9ˆøIlâXú2Øœïl(ì‘N!ЦVãÂı’ ·ï…Ú>/©Q‹¤Á@ËkÇð9—Áç€0‡ZpT%56ð $Ty¾ŠÍ€½†02¥¡¢Ž o`ƒ•Ƈ`òë‡Í¨@bEÝ0ŠNDm4$BÑ(Ç | MBz”+§j™ ¿ÐacC%ª€Öä†íp9¡Öˆ|Dƒüæ Àa ³ˆ› F‹bA¼zx—,ÔT'zAB‚ŠIüTA;”àH Â[ ¯¤BW0,kápÀ ñbí2*g`Ú‡¨9ÙaÜ^Mø}È f!"Ñdz¼GPBGã«°˜¯„àp'ܱE¢„c $ÊÁ3· ÀSªÂ¸–лg„28AŸ# e°nƒ"O ñ)‡¿˜?¨â ÚÁ؉gf^$ &ø‰nMÂv_ÈGÀÂXÈœP£¬Rä,CAo” ç¨b¢/ÒT ÙU‡ø9³áÛD˜}}ª!1¯ G$‚F· À˜jÄÝæ'ÆÐ™E„ÿ°)©¡Zà B]hƒj `Îû†­`7aÆ3ž0xIÃÝÁ±¾[tDŽ1Ñû “1D´L&{œL…è*q¡`î rx^òCTkÐÒÅü7ÜÌsΠyÍCé "‘ÅttEL¢7ø*È”»Àšì¦…f,â¡tv ¸cÎ9–¢ÀÛÆ‡€:Mßûjà~¯D ![‰”GÀÂKgÇÐQ3‚¤^ü ¶‘…é¬0ÿÁ•_ lÃ{h±Pì;˜$>mBËrð†é„Rr#i¡!ý‰F8)^¡XV -¸\ÆVàÀͶ†£86Ì!é‰àw§C×ü•ñyQLD6‚/Gå@’‚B¼È¼P¼Ÿ†€2€!¡” w¨oƒ“nt òU‡È0?ð çÓЉöÄjx$,ð²,…ǰ/題® ÐxiâCiÔ$°çïtü=Tø3, „½D@¬"Þ‘¥ª.ü!…B •h ƒ[.¯€ä,‡W°ÜÖ͆d¸2Ýá”É •àd%ƒDÆ0Å7†!$0Ê¡éñB@y¡ƒÉˆ0 ð¬‡~\;·ÛúÑÀvC­6Mér‡DŒ9éÍT\raC†\ðááœ7ûA½æ ÞÈnyCo~\°ÙÆÆ`5ë!­3 YøjFCNJOðÑ…†ƒø3áAœä K áƒûìÃ@ý9âÀ>àáõEœ|vƒà0â@ö1ªä=¡ç*xÓCÃûîÞo„;:ذðtþ¤:ç/Ø9@AÇÜ.xpêCƒjú€ÞÚî876a· ­m.„`ßùˆTÐBqbâƒÄœ ²Q¥ @»â6Ø€&Cý®ÏÀýåà>ðõŸ8||Ãà0â@ö$‡¨ð= æm"8x”ÃÀŒå î ‡h|;AÖ ˆtƒ Ræpæª1h9o!ب¾8Џ„R¤"z‘óˆøDR¢ ìùP‡Z7°!¡a ˆYäBšõ‰˜ƒâ„^ »±üˆ @ÅBhØ€&CýËý^‡â\>×ô–•|ÝBÉ@õi£<ÝAå ¨xÆÃàøö÷D @Gà=pÞ8ŽDp¸#lÁ‘ˆÍ„F3â0rh‹"ÄU’"’¢ˆ– D{B!æX‡˜„8Ü!©1 \[B"õˆƒÃD ²Qˆ,@¢â< @ÛCûV»pýw‡çÔ@ç¢**H••Ä©Ž%3q(Ç ?”IÇ‚L¬X’V„0$^ñ"/‰ tHb?뀎ñÄs¦#‚¡4ÑÐFYb0ðwà‹HDVZ"–±»ˆ•¨Dqâ!‚üp‡Z7~!žA øX¸BŠbxŒ¸‡„::&Áá5G £øLíÂeÞ à˜£Áø%öÁ.á‰pKKXȸ0•Q§%‘( 9TI’bJÑG°‘Íв$6Q шþ¼G·b;ùÏ`ŽDl#A'ÁÌEÖ",ïX ŠZÄPâ#KñûŠ ÔP<¢€UöðŸS„÷|'¢á‚X±(•„¤¬%±'C‰2°IWHÝ9 ‘\„‡.$Q "ˆý,IZ"™n¾(¥E)|)2áHÛŠ@œQÒâŒîZð¢mE|(iQB‚Š P3B€ ò@Ÿ!„õˆ'“A;¬‰Ö\N}Âr,À›„Ùh&¬4 ›ÄL¢Âc; p—ç„»¸%Á¡-, c Jãâl›]ЫӅ[|*ÂáU[ФœTòâ¦9%H¨ÆEC)þO( sSf™‡¾(¥‡)).1H =|Q¹âŒ Q¢ Ž(PQAˆŠ

'»á=b ç(O"wï¸p‘„êÊ'HA9m‰Å,N Bo¢v›„„Úb&ÅH =QÉ‚„dP¢ä(œáDj 0Pß"…ÿ)¸¡ET('±@Í äPB~aìŸ'Ä÷à'°ñ=#‰å˜OÂwï5(±K…‡n,$`dŠü€Wµ"¼Õ®JÅo6+`±Z1 ËHV(B¯²q«EU *’qSËŠ—TT‚b¢j§ñÅ=þ)àQN’ qpSlBšÍȦ/Å/Š)oÑKŠT$Rˆ"“.’h¤[!(÷GKŠ7*qPT Sãž7ì@§07¾)³M'‹-¸YWâÉÞH°² E ,jQbâ ðX€BÃ:°^’+þ_w ø˜W¨¢¼KÜ®¢EsP+Ž[ó ÜVÇ¢µ*¢H¬àEdÜ+ÑXV ¿,Uã‚®Tl`«7EWø*´ÑU6 ¦ôU¢¨;ð©§EKÜ/&Qxƒ‹¾@]ÆBì»Zèºy…ÐÞ.orÀ‹`\L"àÑúзr…¸¦-¬1l™‹aHZî"Ö¯µL…¨¢-7iT GZ#Ð7z°³£…›(,ÌÁf ,(YKbÉzD±î|,]ÑbŠ‹lXgBÂr À°%Ål+ëÁ^íŠóèW€»QÔH®jr$+ƒ[Á Ú„V¾Bµ*£¬ìÅeÖ+#ÁX­ŠÃ\¼¢å"¨¸ÝÅŠ.ApŽ P[îbÞÄîP·@…¸¦-µ‘mU g$[Ø ¹øµÅ«,-IÁiö‹KÌZBBÑJ‚€³ÛÅN,ÚÑff 0YaBÊBJ@²… ,kábXŒÂ÷°°‚¾, q`Šü€WÎ"½©çЯ †ª0‡qƒ€ ˆ`ˆƒÍ °¿þý/С}Ö èÔ_Â÷.­¸½…æ¾/'áxô Ä^ ïwux»€Ú .Åqu» «]?âéB°¹ÝEÍZ.^Qr‚ ð\kbâz ¸4EÀ-òo#‹uü[¢Û¤Öà¶x…²-ƒ‘kŸ‹YÜZ²ÂÔœž ´¶…¤$-1hA ?°YábÎul ³?…˜l,µQe_‹'ÜY)È€>ˆ¿þþ’/è~é ô(_…"ûzÔȾz…ò/…¡{É ÚÄ^ÀBõ!£¼Þå`/ xƒ‹Á`]îâî–o8»;EØ|.µÑu1‹¦Ð]BçÙ8ˆ¹…ÅÊÐ.HqqÆ‹‹\<‚àê·Ê¼\-Ùn[‹p„[hÚªÎH¶LŰÖ-z1kz X°Z²ÂÔµ ø´ÕÅ¥P1þqDŒt¬cy£oÈˆÅæ†,x1JÁ‰šŒG\b éjÈÃ0ÆÄ0´Á…B &Œaƒ,;èÁ§ Ú0RQ‚" T`Vƒ ÀEÿZ/ìÁ ôŒ_Ž‚û¬Õ¾€Åò/…¡{¼‹Ú`^ºôï p¼Ñ…äÊ/Ñx^ ¿]ßBîhø»ÅÖº.§ÁtÚ £°]¢çu60¹…ÊÐ.Jqì \L"á˸E¿-ïao h,c+ƒ”¿(ÅÇF,Ü1XÑŠ{ŒPXbißޏÄJ Ž0ù‡[Œ8 a¨ _]€Â³Æ@0“ñ„;Œ¼`ÙÃ)(ÁF\0+AŒ,`bÿ{ô¿t…ùâ/¿q}¤ é8_-¢ø¥½X½²…ì/Pz9 ÎD^_bò3Œè¼5Eà.÷qwW‹¸d]§ì¢^кÑÔø.ža›«Œ×äf“c3=ŽøÌ F^F2ÜQ–3Œ¬$e2C(5èÉwJŒ2Gá‘猌dGã!@ÈF>¢1ê!ŽàŒtHc‰C›Ö˜Æ|†2†1†!‹ÙŒ[HbÁC[£ÐÄòÆ%Ô1#±ˆ­ AäaùCéqÃP¾0»…[ (a$ÃE;èÁ Æ D0O1üŒ Ä`JVp¿ñ…þ`/æ~Ð ô(_ˆBû¬× ¾“…ó /| ÞH^ÙBö4«`½5†kò3V1šMŒÐfg£2uŽøÌEÆ`Ð2ú—xŒ¸¤e²c,²`àÊÎÆU2œA”~ ¡4dð£&Ö/¨ÉQ†Hü2<ñ‘ƒŒˆ˜d.ã –ÿ8ÇÁ†<®1ØñŽJŒo˜c`£V˨Æ%/Ê1n±‹ UlbC²•ÀÄ|"P1ᇿŒ:xa´ƒ Ü_ÂÓ:0Q„ŸŒ!Ü`ü#4ÁnÆ J0EÑ㌠ü`M#¡XÀFš 4¿!¥V% 1âQŽ» qðcvƒÓÏÔÆŸ‚4ï‘§16li £L=]8Ò·Æ”’4˜¤u ŒhîƒF¬0°ÑS†‰>4=q¡” €h9C@é˜Ï܆}T3áAž™Œòtgwƒ; Ñ`Îe†qj3~Ñ›Ÿ ÙtfµÃ4Í ðÌÏFdê3a˜rŒÀØeçƒ.tn(Ë9X86Jq±½ˆØl_“ñ¨×a†¹à5Â­É k(kFƒYlưÖ†®ð5k« UHj—ƒSôšðÔ¥†¤5ñ¨D?iåcNclØÓ;˜H4¸á¥V(\i&ÃH‡=øÑÄŒ4X¢hÀhkCByPÐ:F€t3÷!ŸHŒ÷ˆg #£‰FE€áúr8gÂíŽLp£ƒµøà•ÇP8À% ý¤oÚc~ è‹GBü:ÐŽ~ðsÞƒž^î@çFG99»±Í’ŽiØs<™ÄØåôÇ.z9gQÊïŽT\r“C“Ò™àä#¼9aÈ@>àqá#ŽAmXã8Çš8¶ÁÅkµ= ‘ì­czÿƒ×f¶€õˆG«=L1÷9·Ô}¨Ãì°`úáÕª>£ñôÈ£è}£çµ9ÀùœËæ>TAòWü|m#â¡ øWÁ¾?šÑü˜á ~ýc÷Uµ0ýŠGêô?NAúÎà~^òsŽ üK‡á0>þ‘÷©º}ÁÃí_fI@Hr@;† @€<$d q‡ÿ?í¡ÿ.ö¸£üiß`þÉõN?ñü¤ã0‚dt w¹˜Hd@ÓRC0$kD Ý P©f@…2Þ8€Ò$â *a'H5A¡’ Îc´ƒÚ ¹Y«ˆ+þAX" iQX‚qÄ “Ùs"lAr•´„šä$Z!YˈDþB’‚„äx ÷Ù“;žAÐrEÄ”†$0!|© ¿È\ BÝ2’²œ…+{!W) ˆSrB:òH‡|d;f!Õ¹ŽˆsCâ<߈†ì¤6¶!±É bˆièCEâ#æ‘xˆÔ$F$"+©>ˆ’D<Â!Ž‘ ˆADA["ñ È¥ÞE(²(îE|ŠP"}±ÁÈDݲ&¯3 ‰ƒ$Kœ"òkHº`EÉ¢.‘m¸‹^$Zt"Î)R±2EÂ+¶‘¦\h„#?qÏÈͶFbÂ2ב”ÈŒdd#¹4ˆèªG:b9¡ÊLŽBÄq™#‡QHß®Fô?ÈüLϤ~#ê‰5ø®Gº‚=¢)œ‘:$‰;$Eñ" VHrâC?’Vˆ’¤¤”¨$ŸÉ$åI%ÌI("P0ð“餞Ð$ò™*óIVnJ«¢UÚ–¾¤µ‘&Á0^Éšfñr w 9ˆ,tUÁ€áÀbp20¨ †êx€ÈÀfð5P8 ì€ñ‚€ÈÀj 6Ð8 :~Íx€È€f€5P8 F_F€¥`Wà.PÐ Œ¤nÃÏ@ç vx;x„r[5€£@U`+ðˆ pbUÀãÛ n¸8X,xR·€Š@I%° 4~è}ÈÀj 5p¸g!œàÐðjp6Xd#µ@}ÀD°"Ø ˆºh@¼@d`2 ¨ Tî«ëÀüƒàEà% ” .I½k@»àa1 ²yS¶àÐs¸(Üï)@–ÀQ *hø Äþ#‘€Ôn :ØRY9@¢àT+Ø´  ßø„ÆÀe¸4œFjárà>à øH lø_€´@^ 0( ø¹õ@‰àH%˜” E¸Áa`µ ZÐ.LÐ IaQA¹èPÈ ´µ÷€’€K`(Ðð üÌñ‘€Ô pà;Xtžz‚Y6@¡@S*Hœ ö¥ìA„@É h¸6°ºÂaÉ€i`8 pÀ¤¶pF€¯`Y@/ T¹õà‰`H%”h î‘AR@¯@[P0dŽ N烚Aâ %àð &Åî}ÀE#Ø 4dÑx€ÈÀj 8„¢:O?Á) —`NP'p\ «¸žÀØÀph:b#/—€X@,À0 à*î@–ÀQ +˜D ÄFU»€éà|AP!èn ³h?`© [h1(è œ žÝ`ÐP¼^a°€dÀ7`¸¤y[F€¯ÀX/, Å“â@ûÀƒ D°#€† Ã*‚ÎA„ Í@jp6È,”_€4 Ð x¼ÂaÉ€q@:`pH 2¶V€¯À^ 1°( T¹òÿà„pF€%Ôj ê@Ôàmx8XXà™b2À ð xÚÂvÉ€q@=0pH lÀXÀ± ^ 20 Tû—Þ€ý ‰@J (œÖ ~ƒ–àÒlÐ8xÎq€L€2À Ð x¼ÂaÉ€hà8 pÀ¤¶dF€¯Wà/à ŒªeÆ€õ …J((€l ?Û‚óA„€È g¨6LvÈ ‹3€%à  °èþ^6°€a`2`P(Ü/)-€›àQ +Ð$ Ä #ª€ß w Ap$ â u‚Ök@¹ `X2 ¬’ˆhÁÒeAÚ°8d–Ð~€D %à L&®€â€}À?Ð"Ø l¿i¼@a€20¨Lèq‚jÁEÀ© W°,dì Y"A¤`Û€ˆ¨‰™(ê€3€&@0 °è{R€±@Z2`p(jï)À–ÀQ +˜ø ÄFUÀ÷ ˆàK'0\ ’{½^À¶`a2\† ¶ OŽáÆvá³08d˜Ì€tÀ?@$p€ üˆj»€â€q€>à!H l¿o@Á@j€8pøª ·‚sEÀ© Uh+X` ¾ƒ+A©@õ0²hưRD7@&@` °Xê /°€`à2ÐÐ î–ÀQ +ðˆ ú¹‚ AÀ“@LÈ'8b ’I½l ¼ðbp2Јl ƒò„pàP àD¶–Ü~€OÀ20dSÅû€‰àK`&8h ,?tÜ€û`„pG%˜” ý¤]@´à]@0xÆ å°„ p«èž+¡€L€2 ` ´6‡€É€q ;€!0Ø ˆ¿Œ€Ö@s°>° è<ùZÁ9@¢àT¨,èö À%¥@ÚÀp°VÔþ‹g4À&@ Xô)/¯€X@2`hHêÒ‘_À½Àh7H,h$' @–`Nx*<ì m߀Πj6Èd ý€"€À àpÈh–ð~€KÀ, X(ÜS`H€¯À^ 2H T¸òA‰àH0ÄÎ ^ýA¡Å m  F–(€€   ÐpÈh–ý—€Y3X¸¤¶O€¯À^ 20( T¾‚r¡ûÁ\hóÔ~ 1ÞÜ‹†i¹Ð8Q*Pi‹‹yBÛÔ0ª$7Ò? U ”pOœ'èÂc„zFtà]˜-%X§ O‡î…é$ ñБ54ŒÊW"m =#x£pãM”.Z €…mÜ"*12á,ŒÐL7²~‡ÀÃz¡W ­¨T0-²C ‘† BY!F0¤¸ÀÔjg3€&@p è d„/Åû€†`E %°D 4~S…¥ÂH¨Äs¸AÁ#W ÈüƒØaDZT›‚3:—‘V†²GÊŽðÃ䪺#g ÛŠ½ˆ°ãßJÂY¬ÊZm­(]Œ‰EAÞ€ß(h 3î~†¾jÁs ¹K”<¨$c1;ÇÚ±éHøÐ†ü8ö€Š¤»Çð2Û¥ù {‘ˆjEñß(X±ypÂLª4'1¢sTm‰9Ôª†ÌéLYÀ‰œDŽÂ  @ÀO’( ÑwÀ`8¨œ ´€h@Aà+@0 é €ÀKpA >81Àà ,‰1…àíq*ðÿä©®K™7»£aMDeH§Ýtí–£°£êÎþãïPâåóÈ ‹þ5x‡—’ÓÞ/³=MÐÀEÖçH<£_!l¦üm.EY!‘/T¡ÉPÞøè¸ 0¯žÄ ƒuÃAZü÷Úuå?½–ÞëÂ~)—(F¦3i6é9ÒéɘÌRQüSœ0Tÿ'[…%£i”Í÷“! ‹ù·Ìœ^Ì¥´ÉùÄËœI}Œ”Ìðe|È×8–Ξ‹BÀ`P4æZ》€Sà, 8 ˜©÷KBÐ0vhtp-2,ç"ë•úoâXÓ¢†G :Š[F%h™RGë >+Z´i÷­Å<%í2Gf3̆"G+¸¨ÕPÌÞU•¦é;»ÙÚà ŒëÅ/a btÏä°ÈÄ7C0ñš°Ì“HA+8† Iì1c!‹NÂ@e3Ñ hq,A:<3‰“óPh¬¸VÂ,È%)g …@`pøê‹ý‘@L,  ²&ÅoB$ÉÒÏ2,@½2ER7å·bß[Ò²‰œä¸þêTvõ¼ã]i°U‡â;Ð òiŽˆlо&ÇZjì—È:íÄÁ¡1ñZ‹äJ “0cyñ;Nß“¹ eZH’ÝJô“3È_C~Å2âtŒÇ4@ö3 § 4åór¦x„À Ò—6Ëòîr»ÐôçAžHËð$yÆøuK²Á͆é8xX»Ï\Ó/›x®äw*;ñ9““y»)á'Ѵ׃s‚Ùó§³~8G ååóGÞdiuü~ã&uEEfIßʆÄêêtª,Û‘øÇçð6™ðÜ­®I"G.Œ) 0à !Ë~€D %àð Â`× “û'2ô™¥FbŽÅpYºBߨQT© Ñâj»'ÉŠnEIVíþçp«ˆ‘ÄÆúHá¨6Ô¶šû½¹É8þ¦…°6›Üùïy'§”«ò[Õí}QÀ¡Q­ö')óõ:_Ví¡€eÆå^¡noæÏQ˜tz\goŠ'hPŠ¥Àæio¹y™7g ²@ZàFÐ!è 6OŠ8÷™!Ð=¨N&®¢E= ʘ*gU´Æ!uI˜¤|ÄÂtAÔ…IÄ›\e×$Kz=ÓPÿ¤†HGoæiÕ»h n½Ùxüèo77FÝÁ„ùŠ\ý~ï 3uÑ»‚Ûhm{geœ2Ò H×Û4AÉØwü¥¦‘lDuú±b⥊§Î³rúv5@„šËEØ À XÂ$/üA¾pg°;hˆ z Ô“k_ÓN‹v +,Q²æÓÚW ´žL+¶òÛòjAEœ—Æ`,Ð×—ž»fͶBäBvŽ@øe±r@y’”ƒö\¨åKm0;eÃ-;¶ÿ[ìÞHO?\…§½¹\~ ¶ËHuÈýÃ|ž4”¡†@º4 #˲oÁ—5{¦õÇ*âtk5ðYí ¯VJK^Áçi€……Ɖ$ô0ÓG›T©ÃNÞcwŸBá¹³ƒyÊtÆæ7ŸxÍ4þ£Ž VšËvÝäÕ½–ëDÓûθ‡+¢éÒò w]» !§[H$&>`ú…sº¹‰›ÀmÇ"{Èaõt-¹"ÖîJ–ƒ£K‘·ÔHy€L€-P&€5”HŽ7­>Ž–EŠ7±‰e/3Iœƒà¿h¡ˆ=„©ë¢ófo7‰^N<÷ß‹ãu÷ŠóàƒW¾0àD¯£gc”É® èÂwëÁ6–ÎYÆÂ³ƒµ¦ÄÎbbÚ‚4"£csŸ0ÚÆGÔ[i5e*ôüá3Ñ╈Ãoàg$—÷KÆñÎäÚãt6@êžðNò‡c3¹ÁîTúöغN[îŽo6Á·R=áwŽ5BÙºlÚ0@`Ö51á°v1"s|XíÆXíAÂXÓÂgàRP¸hL" / o‰Ÿ¼ªÞ*oËG“dꇵ}.¼Þ\ð.²7HSòéÒbÚ[p ¶]݇H[DyÃRÔ7,#‰‰K^w‚+x%1Qíû]—1gû&«\Ôßž :ðƒ{é=Pî^O˺ÝÁfÚw.B…á 57-;„åÛZñ¼lŒ:µ:سúýË0ß§cMlzù ÝfHÎÐn½ÇƒæQ¼¥|n™%ÃéÛçvs<›dnU†³K…Ã÷Ž:ÁÕŽAgëΉÄÂáij¶¸ö°Ç>Ux&ε^ÃÙÜÍ/>¸füf‹me?KËâ'·_›}Y´–Øþtc5O\O¥‡º+ï Ýß°t_¹‚›&M2ÆäÛÍõî_¡¨ÞØ ,ÊöðKñUqV¡¯=B=NÝç¢0BGšÛ©Ó8æx€8ŒÚ‚í ¦ÿKýñ"ëñv8‘š÷­Ú–² Ãé+Vý£òØl—w¨¥76\")‘€M¾¢µð—Ü4ûäúŠ|›½Úk‡¨Éæi #}à·ZšPl÷ç/gv«ál¥½)Ù½(¸²ôèÃtgT Š’åHl ¹O¿§e‡M¯ÎÊ™g©6\Ý9‚7êØѧx̳pýÑ+© Û*=JÞ”7#·‡øFfÖs[8ÿ L>$7µw7èšylrt«ï¤úy½6d™m È:Æ•u²ž£C^˜ŠÇÇ"D0ûÄ<ôÆ-ã–„OB`OÖÃͰÀÙ¥nü;í\¶MZ¢U"V›5ŸÊ8£Þ¨HTöòÜ|–Àf"Û(LBæíqÀ,f4x›ˆ åMOÂt±¯„P>ÞJ L£Œ×êèK€ŒÌpŸ¿ÌÈ¥7š¢AdÀ±«`Ëħt4ayËäEòúð&s§8›= F×»ˆ1ÚBòeW«!SöjK•ʪ’p+8³ èG; ¡Ð ׋;¡íµäÓðeV·J˜ÊL­öŸR×MVûL§NgÑ”é,ó[h®--кˆÙô&Ôdùâ´zdÇMàÏ2()ˆ 9a™ÅîëîgA›Rd—]6‹˜º ¨/D¼;[U®d¤4ãcífbræRO ´®n´=šÉ‹S$Ôò²A]D§vK$`.Èh<¢ õH’ð[Ë.õ*IŒgb€s4YÚ¦¤ §«<¹ÂMänsuÜÊÆE2!“‹Ú\‚Ø–œµ…¿+‘QJNQ‚‹ˆ§e`&i*I&HÂI˜dîÀ[ÈÄCb ,D!‰ÉL:U.Ó—ýËyGž:±Ë=òQ£–uê™jq‘‹ÈY¢¸ˆ®Eš.áHrcÝ!# àUâé™LÛ‡o@R,Ä¡Õq®Õ’m|s“Ý¡ IiÐB«¢ß0žÄº$ñ' xO"¢ ÄF¬:Aýd˜%2-Q‹Mrtã÷"a)j V¢ê×g8=Ɐ— êê&aˆ<>á𸃄`%ñK‹`d#si É4PÒĘ<ÓÇ6>Â!RxŸåf.‘‘ xs»àá5|PüFaù`kC8°Õ‡$>b' ªEì4±Ó4dð+~ rSå¡é&©ûVR陨7C>V1ޘȂƒ”`·…T)AQ Pd‚‘ Zc*PüˆÆM¯¤ÏÇ>"ÒjŸÕh®É“Í–tëì!£ 9¡°4Ál ðG  ŠØ,a™¨†DÈ+q‰ Ð{äR&iTËÀgƒŒŸ‰â&’Ä£e‹0ŸMþx” bÆ#@çÜ%Àò&@ö€5$@á¸TÃ.!Š4]ãYYÉ–U’øDç‡òEš_Ô®³¦´¡ÆOJƒˆ°Ä†p½¬@µXÀ¬/ô Õ`RƒÁ 0^]‘É®Vƒšœê¨Fšiþ¶†-µuÍŠ…°¹„¼ÃÄ@±’à!T žpA‚ŠÐíˆÈR÷0÷ˆÀN’¿p؇vAš?Sž«Î2U³Ž±~œAa&(1h'àó  @¶¸O€&˜`£<<9ÐÀÆì?:”³F;79ç¼’Å+¥{LØo¿`K çÜÁF‚- ÀU‚ àCl€(ÀdÀ7‚hÁ `eÃÔ$aU Xqd $‰HKxf#ˆŸ1 aQòÊX>Ò=EüЈÜa\»p’@Jp €tLˆ'¨«†?BXðˇLBrY¼Æ:–™õ@­½-stKë ïÁæ"¡  è:Lð"€œ€ pÀ`ð;˜Á (mD&ñl0yM&Ù] ,l3½ ñ!iäVZïÙ|Ü×tÀRÑM‚T9£ †ƒ€TxÀPl€Uø,AØ༇0EŒÈÜÞGr…œÉ¦þ=Ò R¨£50Y£n0z” ¢A Ø®„ìà¡PÀ@À € ØÁ 2!è8«Æ@9’’¨¨á4YÐŒÔѪo vl¦_…¸ÎDâ;at°2`TÀ @NP6p ðkÄ&Ál 0yDQ' _ BmÅ!9#éüW*ö™ºß‡Àö/R“(Tð ;$à @€LÀ±`Lú1 \`à # B\4pûh¥KÒ—’ÄF§¹™ñÁ2ß×ø@q‚€ @AÀ `Œe˜2‚ ÑìK¢ÈØî|LÒ³(×q>‚ Ñ2$·'uIêÄYâí˜nË–Ÿ·!Üð…|S£å)™£ÏÜÆF‰7Ï:ä1£)&©¢P’¡ô·Eø1ÍžÍ}pKÊ_ˆ|FfGÒ眵újX €>€ð €È {h:X戬R"ÿ¸þ L²‹¶†2Ù­vÃæ ½ˆýK:u”Ž«Åš.½…̰i«oœ”íÇ·À1B,£¦s>šN cÃYÀö4EòS“ħ¥Œ.éŒMnžžlÿˆ`F:LS< å@«Ýn ícc<îàG¼‰öðR‡|d$i-éÅÐþž¡k 3$0  @Ð @†€Jƒ4!U („À)AeŒ gÃzÈþÈ~HRf”d¬Å¶0I—jq¶5è•GêZª¤…]¬ÍuÌ,ekL›vägl=®Pœ‰äx%39ñRVªKð¬ÅÔ21¯Žt{Ä #)+ ìT2È—ŒÆ¦Œ7)Ð@€2£)&‰ P‚ Õò·%÷±¹ž xp£Þ@ûx(C¶1Ò2–Üâ¨yOÕ…ˆ!àË „ ;È Ál ›†;"¸šE:-1† pc ÉMb´·Æ31¯N0wSê ÙiKzwš¬œ.͆,²i³oœ˜í··@ñ=¢fi>:JÕBÁvÌ ðrCì"A+ WÂõxÚ‡P>’‘À–å*ig ÚdK›¼égª@RѪ“ôÕ(eQk[ÚþìÏ–¿¸%ÒÏ&}äáå)Ë‚q´?§¥k¬Ûs0Þ|" ÐàÀ¨ð€Ä@P¨)ºð¡…¤2º0…†'aU „c#Sˆô"ERM“¥Å|.Y‡Læl£’žüBEBDøž•-+5h«¾aã/Z‚܇*;îð…2 •Ä÷* c˼cB›tæç”?šQt’$ƧíMŠßZ²ô˜ÌÖ¨·iÌ®ô|<¡oXûÊvi“û¥]XìCn;ÓáÏ(€¬@9B p¥…¼2áÀ`†D'¡V‹ŒcCT€óˆEK“x¤ås.„ÌÌkÊÀùè/Dš>Äœå*½d«ž`Ë&4ÚºÕèï݃¬D#_%Y~ζ‹µ®e¢n›ŒrfØEÇ ˆJÜ àLð ]ÈÁ €b„ ! ZC€ñ-²•œ×¨%LJ½XÖß¾ÄNVt_°5œ Àh°#L oð#¡? bCb±ÐLb•@¿†l6ñÖ¨…Dm%‘>J„XòÐFØ9ãÔ„´W$U/ÉéR²ր»†2Ŧºr³ÞÀÿHGDª9rm˜¼ñhïRºóÚ’í0ÇþtµQ¸q‡`0¡@86Al  H{À@êÐRƒ ûØOÀPÖT?â,Ø£|/1”ˆs£Ú Ñ >NR—並3A¯N(vÓå ¥ˆñJÊq`ªŠ.-€¬‚haÜ `\°@™˜#ÀK¬€ßèFÂxðÁ†¤:!û8•E+atŒ|jã‘iÈ–Hòi”h¬¥°/ù” Fo“©¹hmFzMS> Å=ŠôIáñ WÂP~¨@Ì-Á^ S˜`¸h9‚🅀0©€~DH%? À\Cpᇂ?ò˜… *™g‹Ôc³F›ˆç'’?z‘bPž”" ÿ€8® àcƒ@Äh7Aä “,¡‡ XtCò"!' ìU‚݈цþ;‘úÌŽd¶'ÙP‹]“™àÙg";Ñõ…°&Ñ 0Áj ˆNÂN`ƒƒìè8Âpy #!2 p[ê‡ìD‚Nت…´0Ñ¡ àv#ì!QIVNòš•ô¹31® Î-!R LD`†„ !(CB4À¡l.á– ÀvÄ"(‰ôUBÚXÐê:ÑóŒŒ$¡'!JJâ[³™TG‚tƒh À…´+aL øLÂV`’”%a5 U‚Ú`ч <¢ x•Å*Ñn 0gãsPøÈb‘`’„Ò(˜…DðT9Ç qC’?âp’„Ô(±W‹X_ã)ÀáÇr>Òp’ÄÓ(˜ŽÄN!a‡ø>áòˆ|Ãò !ˆ|FbI  E@,1t (5¤”Ú£UŠßcÔ¢–úgN á@(¥(¨+­¥ºØ¢TZQòFIÉ]/¦„è |â¢þ·Ú ¥ Bˆu"äl’BSL ÁA)hQãü­›t*Ö»9sÎÁá=gÔÿ t…ò(F‰ )¦tú¥UzÌ]Œ1—µ6òè^Sôƒñ.¸1cœ£št›V‹6cŒÁ¥6&ð✳¢vì?H-£TžšÔB©YK¹Š3¶ÈãËå‚Q8J£@éµi,…¼¾£.hI®6Fäáœó¾|: Gie<)¥|¸ØS2kŽ!Ú>!ã| šTœ²ŠT‹ r0$Æ™(fÍ1µ8Çlù ÔT’SZŽVki2Æ®à݃ßðþ8J)«B)á#„ ›”’¸Z‹qo.%Ø¿˜³8l9à?¨q¦ªÖšýe QÁ;¿" s”Óf†Žñê?ˆa&E ©•žTJÁc.fÎS¢{Ђ3JéùS,õôÉš£‚v/Š ÄXñ*çΣ@kàAá7&d¸—2zRÊér1f˜âTŠÒ’yTk9}2vªá]«æƒ.?K9Î,…x®BäbAÐ?Èq !D8‹’BlRË}3fìî N“Ó£YËí•5—îßlŠr^ A6%ˆ‘¢tT q’6Gä#ÈHO ±s2fÔìŸäL“ÓÊ¥ZL—µ÷ ðŸ¬)‹²Jc‰1ƒÀuÁèAÁ4)Ř»c4m±þE‰M-¦8Ùsþ‰ÒŠ}UKaƒ³vÐæ^d†‘¦OMI€`c Áp.ÐCàˆbtT‹a7™ %%$µÓdvP+JêX® Ð[“¥{2 Çy[2$Ì´™áx)„°Œ(I d1†àò!„¨¦cHv‚NR Y6Çy#4¾£UÚëcm1¿»'Í℆”2òlJ©Šè6 ÀƒPvpY áØD Áf3GI%,·™SzyŠ=MJac¯†RÖÜsÂ~Ю0Éyg3¥ ¼šàÐ@@$`̰¶—#4u²ZTK¹ž8獔³g-­Ï½8£¤«˜Ó†ZÍ Ø Ø D €> A¨D ¡¤@ ‘h4‡‰&ÅlÁ£¨ÑZYPêÙs±†–ߓ惑JDKù·2§0à(€€@È%a +Á 'ÅàÛ„x¡–“ nO"G‰©L¬•ôËû’xïòÆy=5§”០\p€àd`’ƒ¨c$t¢\TËÑ¢9‡Ù%ü«–óhMÕÔ½Ø%cü¶Ô*‹À€( ^ k‚x]¡ôGJ g1¦Øð Äp™”ªÄ^¬¬¸×€ýa\a“B„<×Ѐ8`0< AðQ ÁøK‹!ž;È2*åôÒÓðˆÒ‚~U«u{0æNÐËsq®™à=§ë!\E’ÎgκHéý[Qj]-%ÔÀØã4iÍÀ9§hóŸDƒÐâ*H©K0fìù¢´Æ¦Ö.ÀX @< ^˜hÂXWŒ±ÐAÉAK.Xßt"‰ÑêTMJL+¸Ãe- ­·GêÜ~ÐFÄhÃdÄ´™ó®ƒÒ:W+Á4fÜåžè‚ú5Ii…<(õL¯–²î`Ìy›µÒàÜë¶zªAøuc„‹”óoOª-Lªuk°àl 0&Àð(Á-ñ&ÅÌÄ ‘2Î^ Yž6'ìžä†jCK)ÁC©åj³"übŒµ£5öðä[Å{ïæ Âè“#ü›–ÓFvКKPjíz²ÅŒº˜s4kÔ=ñ¢dx”“BRª±a­µæÂÙD !T*…ÀÃØ#tR$EÈñ%%„ÔŸ’¨X az1\ÓcŒuÏIûAÈ$t¶œ*šV n/&ÈÃPlîÌ;’øŸä…ñ&1ÇÙ/,¦lè t~Õjåc­UƼxcœ­œ†ðð dX’2NJɉ8'å ¨•ÂÎ\ËùŒ3F¤Üƒ²zâDÍ#%¤Ü ”º¬XKaw0V8ÌÚSboNEÕ<7¸ý`t'ˆ1n:ÈùS1&üú¢ÔƦ֋ h-íÙ¾¸Gd¼Ï¡Chk ¡Ì?Á>-Æ(ԃ؄‘âhM ±9'Å ¥"¶Y qz0¦HÏšÓxrÎÙì?¨9#4Œ–SbRª©_­UÖÀXÃ.h­uº8ÇHï^«î€ð‚E8Ú,…ðËC¤}Ò@M D(å,¨bºYKiw0&0ÌSdpyß=Çý"f‘’ÊlP QT+Õ¤ºóem ¬6÷çÝÀ†‚D‰!>)Å€ºÃHpñþD 4(e4©•‚¸X‹Ao.æÅC@jÍÁÆ:‡Œù $$‰ªGK)±@)5N¯Šæ_ŒE”3æª*E€¹C4maêA™$&¥©²ÄZ is/FÅ3:iÍ™¿9‡dôd …‘27I)m6¨&©ÕÚÐ\«é‡²Q>'…¨bèa ±ª8Ghû!$\““‚ŽU‹ j.%à¿Se é¦6ìã3À{Oâ CH©¤´º›Ô ”U íh.Eò/†(Ì£xtRCÈé,'e(¬bà^Œ ˆ1æ\Ïs`nNÏ;Gœú $ ‡Ñr>Ié8¨5,ªUâÐ#e ®7‡0ñ¤$‹2`OÊq\-EØÀ“"fM ¨6&èáœÃ®xqûAY#D†”ÓuPÊaU«á¶8‡PñDˆÂRMŠ!R,%¸½˜c"fª6FìáœÓ¬xYö@h=¢´r’ÂhO*)MªÑè?!#˜Ò”V )r00ËšVlÍáÄ9§Xð£èÐZDˆÉ $ä¼›SêŽSä<Œ"ZN !Q+Ŭ¼˜S$gMI²7‡çsÀz™þAQ"Är‘ÒªdNj I’ÂlPJiY,¥È¿˜Ã0i yº8‡8ìÔ|ÏêBHu#D‚“’âkO*!L–U‹ m/FÉ™óVmÎÌ:ç€õ3úЊDÈɤ¤®™’€Q倵—ccŒÑ¦6FøåC¾zO™ý@èE ¢T`ŽÒ:RKé±=(…,]L‹2æˆ×£ŒtŽéç>Gñ!4‰Qz:H©A.&„ê ”‚ž2¦€Õ›s†sŽÑå>í¡4‰z9H‰=-&T䟔Z˜5FÔàîxÏqù@ˆ= ¢D\ŽNK)‘8'µ¥ ¿9GTðžÃî€ÐrDh¹$4š–nOJH©åVuNùë>È!tD‹QÂCI©a1¦Ôò¡‚›U ÔõT‚в!EˆÝ!$Ô°˜“jxPj9M*ed¯ZD(±¤$š–mO G)•J¬UâÉD(±¤$˜•ÓmO G)•H¬ÚÇZhÝ!$Ô°˜ÓjxPj=LªE`®Ö:Ò[É9,¦DÜžT"SJ•X+µŽ´–êéL©Á=(U ¦Õ2±W‹i-ÕÒ½Sâ‡R*qS«%z²šÞ]KÕ€0Õ(§•J´Wë%j-õÖ½˜ c ­[,–µ— ì^ì ‡1–J°ÖrØ\k¹|°FÆÙ31\ËÅ}°f"ÇC3gÌ%Š1öTÍZLj쉖³††ÓšËehÍE®6vä×ÛSupǹ§<ê]¸+èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú> 2%¾£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èM€ X>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èa€ª>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£Þ€8>£¶÷¾£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£€ ¨¾£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>¢”$@Ôú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èúÀ¸¾£èð>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú­#èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£èú>£Žè¾£èú>£èú>£èú>£èú>£èú>£èú>£èú<³4ë(©XZ¡<ë“èú=Iaz­§FÊ¢g€‚-BŠ9á@PÊ{Hx `ðXú>£èú>£èú>£èú>£èú>£èú>£è÷¹Œ2d@ðZ Šhd x €+¶´%ˆI¸sBЀ>£èú>£èú>£èú>£èú>£èÍ#p2 à( @ àÈP€ /…¡¸ @€€ € èú>£èú>£èú>£èú>£è¯€(€P@( @ xPª)6b€Œ …(€P€xï£èú>£èú>£èú>£èú>ŠÈ2á@ À<‡€(€" (¤8È€M‡€ èú>£èú>£èú>£èú3蘀2(F ÈP8IÙ†€ (@xú>£èú>£èú>£ès (€P P€ JŠ“Ÿâø €@ £èú>£èú3èpÒ€   #K À( ãèú>£èú5ÅÈ ¤ Z€€9à (   P P ú>£è“ƒ @P€ Ô—À%€   €(( 㘠€(  (€P (  €PF €hZð¡@(€Hø€(€ F‘€à ((  € < (€ Šîyoš²ÚYü«mUÚ«¥ª¢ RöªÄV)+…”d*@Å*"šÝPðª|NÙ'ò õz’µMЩ^L`&pSb)Ìõ²ƒ±FÔ¦}?,’^©ÿ QP›hŒ„gBE+Jš3Om¨Ü•JËÅŠb×utž¾±a±ÏYkÌövšÓ\ÁµÎÞ‹q 9cÝηzãÉàÜn„7ËœWt'hÎõñö…ÄE £¼u)‡ôêÒˆýN.«ÞXQ­S×<ëæÖ£‰–²Ïvi¸5Ô›cì§—qÒxì‰wÞÙŒïF…Na¯üÝvr :å|˨0ä?:3¡#ð—N(OÔÉŠ´5jÓåsf¾Naf±ËYnÌùÖ+^i¶Öß#qa94îÏ—‰ƒ€Àø`ä1™LÚ&¡3oAÈpív{˜@W¡wQfit¯blýA ¥ÀUo+ûVš‹š…ò» ¹ŽÊ˸g÷µšÿͽVüÃŒÑÍtê)v¾–  3˜RÓyp”½Éút‰ØG»¥CÓT*å+zªÝ_¾´í\详˜gÌ{–`ëA¨ôØ}n.8œyuV[è¨âRÕ)!§ €…erËYu Ãjf£5ñœ\NåGÐb#5d”†M"§ùԭꬅ€‚Ô©tP¾ýaز™•m¨ÃdiºàÂr59ÿl¥!¢vÑ1¸–RJï%êw …IrÈùx¨ÇRi{7½fOyˆ ¤Ar9(¨š:Oþ©hUcË¥­:ê­ÄKdp³U4 \–ΛváÂþå(tZ”»I¾$œò4QT†ØC¹"£þ‰x%B¬lÀ†g™6þ!bH¤?‚8ý(Øš|P/)„Õu‹5²¢í™€–ÅdÕ3‡ÚMíi¶Õz%Ä åútÂIUDX2 HøhxR;¯XÃHTsrd‘Iܱ¸_y3FŽ}¬” ª ]”ßM„(?ÚªÆõÜ­xŽÁ8bü²§YáM5¶¼+n=¾îã:µµeʸ6^«0‘X଺–€ãQ­±$ܘp<¹ûŽš4£¡ÔJ@Ö ÷âΑ_ ´`4x HðÄí²²™wœÊølï:.ãPTȘDÒZÉ:£T|+§Öƒ«–µôC ånÌÍhŸ5d6Û' ƒ•)Î:èéuV9êÝ.C}‘ˆ¬°M†$K Ÿ…Y£ º8ú°ŒÆNO+‹ ÁFÛcªiò¡°ŠËHÅ&ÓÌJG%RºÀ!kºÏ_ò12Y1¬á–”#[µÄÞâq\9›]® G83£UÕ0/¢/†Ãµa½ è˜ƒðMÎ.ë|HÉÄêR·±|€Îno;_ŸŒ¬ˆÆ„™BfÝ@ ¦Uú,gâ«ÅF ûù•ìÏ}iï¶[†.W³ž‘ÒÜë1t":‚ÝyâyýXcì)"Ú Ž‡G„–ÂÏÑ­xù¸ŽbOÚ,8˜2‡“Äò}¬ŽQJ‹¦ç;ê~Ån͉q–½ûa±ö&ª»f»$á~r¡º9UΘ÷Z ¬.˜ÏÇHl¡¹ñ$ ¶ mÖ@$‰”{ËT¦1#Z!Íõæ‚fDÑ$$’é Û•ª§é_~µN]Q¯òX˜Œ˜¦qJU­ÆÛo„8¸Ó®£Ç`«ÙL"Ø ƒçÀÚ@4àNèL$9J&`ùŽZˆXľ¢¦1uÔ˼n:ÿh¢Ã˜¢fÁ@*¦>V,vë+Ê& Ãa–žÏßj!¶ ’®ç"ë -×0íWw‡z€žÀäŽ@ {FtCÑ‚2é=¨°š`á4šœQ#ˆ T?ò<%+ŽœXQR*+UÐkBÌú݇xÈfš4lš¿í¢¶ñÓˆuËÂé†v…µ¹›±ŽX%ä æ  F÷„®ïÂÑ|•’S¬.+™1MžGNÓäÊN’L\'ɪj´u‡êÚwªÀña³1vL©fg3<­¢ÌÓ’jܵó<í¿ï{™Ç‚çxt¢ºÂ™.ç÷«Çuoˆºi^ƒ/äBlHf7‹%I—NÍðh4—Z‘ j¶ÅókQ¹®ÞÒpc¹%Í®ƒ÷P{¯EÛï@xx<¥DlÁ­ ›p: Æ 8ˆ¸ÅycM‘ï1´Ÿ~Xe0lCÎ!‡”²Q0•QM•J±åp*ÃegH¶X\®éWÇl óµÊjfY3½Ú%í5ö¬+^³nÛ¿nß7í\4n9+c Ò"êÚvL»•žÏ皊Ná.šIN¿(&u*k5Mj²U^β:Z{-ëWJkÎ…ûÃÉˆÚÆÐd—²àY¹ †‘óQ‘­ Ø¡mU7,›Õ® çC‘±ÌŠètôºêݬ®ñ׆CÉÑè&$J®BÁ!x á ‹lU22ܳ‘‰–SìY–àÛbuq>|!Ñkèì„‘zV1–›ùO(ŽÔ© „YB¸%a®³Ÿ[.®@—s âöƒ Ñ‹@Èe-³)ÛíöšCUµ¯ÙŸmÒ7i[óŽw›•AÎJèóu^;Ç.þ‡ŒƒÌÍ骉ÜF¨$.’‚ uÔ:vÕA¨£àSlªs•êøe’‚ÔYorºZ^{¯äØBlH67K$Ñ–üÍÂh4ŒMhÄÓj™¹HÞ¦pI¸žÜ‹cg@C§Q×*íRw‚<-žK¯?׬¨œÈCîÐ.*©·Q”èéd„ÊJ”)e»L^Æ­s”Yè5®„îD:¢øÑèé*¯zd¡8°ŸrQB©b•ʶåqêÄg´¶–\˜.òWÌ̦«ñBÊtf]³»$m4Æ«»^a³NÛ©nÒ7æ\1Ž6÷*KœuÑÒê­v:;ŠÝû¯W™#Óì²÷é>4 Ptq¤Tª7Õ"²” Kò&ÃÅjå"ZITz­Wñ¬«¬‹ÕJôÕ|Â8bQ1ÂY,Œ»†o“@Y¤ŒÔ}kL¶,VíËFõk‚mÅä]sº:¹j{¼ á\òVyù=bžã(®ÐP&c~ŠnÇ#@áÕñð“*QT,˜9M3ŸAÞ|öx~ÛA0!y*¨ÌT€êMÙ-\™ßN(bÊaUH"¯•]x±ŠZ-¸×0«Áeõ }‡ Åëd&²¨™ìò†Š£N «D×­lÞ¶ð›·­ú÷ Ûåʰç(txº¬]Ž®ã'Æ%æJôÃ{,½ùß.FóC—aÚDôd}»@£¡/Ѻ$x I!+˜´Më'¸Ô=ŠN…>òªù[°YYˆ­q +°%ì3-„îÄãc¢²g|,â&‚ãJ%©ZÖÇlf6´ÛšÍì‡ÛŠ‘ÈöæLt :xsîÕ—xsÂíäÂóúzÉ=ÈŸ£·ÝÈÕXbÌ/6‹îWƒraåq Ä“‚Pé,éÌᦫ³s9È8ëdyF>c w¨sTTŠ7¹"r”tKʦ­¹Š eJšùS<¬wW ,€Ö•«uuÏŠñÝ~ Áwað1L®FiC=‘£,Ó¶jéµù<¾vï]Ã|ã¢r¼¹Ò!®¬·d+¸åßìñžyš=3žÌÏWËÛìøþbæ3FšˆM¸‡S§iáØø oAr!‘4ÈÏ´šM­-$™´Nc'ñX*[%DÊ­½\j°ôYÕ-•׫·ïëÕ…ÆÅFcв{†,æö…K!©ÈÖýl„6Á› mï§ ‹ÉHæ{t!º€]w.×7yÃyäöôzÔ=ÍŸO¤×ÞSõ}–:²ë œFÔ†ÜXÿ”ŠJK(– ææ+2 §ÚˆpÊ:%ógçë4šá‚ŒG¤$ ’µ‰ŒDÞZ{5Cœ¤¸SÉ*›§k•¢Õaoìº}^‚¯àX>ÌDö5K#ý–ŽÍgß4zía–Áh¥¸NÞp¸{\yÎZg;‹¤ùÕúì­w-¼ž85·§{Ùõðù•}Œ¿%Á÷Òx±H¨ª²X™-öÑ VæaƒL‰³äàÔsØ; ªOÁˆt% ‚ŽHÓ¥1’üI®ôGš¦ªTÃ+•á+£RÜ=s*¼_I0AmL\–@ë)™NÎÛh4ÉÚ§ítÖÊ«m5ºß8p8¾\š®jwCƒ¨Õ×àí›w¥¼?^TOCw®‹ÝiñÈúi}õ¿XßÚP"áÄ}„> n;H…¤†¢W)5Ô zS+ –K ŠÅùS˜ÈÓlà8áÎÜ'£ãì:i8‡dEJ£r’i@Ô¸Êhy:0  Q{©uÕʶåq¢Ã‘g ¶ \Z®ÎW¶LkŽzÉ‹eæ3‚ZM$¶£3YÕ±Ú‚n?7›œ ä‡"S™2pžQ‹*#ÂË>ÅσÌÞi¢6tNl‡jÃÏQô½Ðƒ¦Cl¢‚‘¥‰ÔšÚY2ÆœfO§(‹T Ê~U"µq`&²µZ©-ø×L Í¥úsåˆ&ÆldX²¼Ù¦,õöŒ3ˆ“(G>#~ˆã¤²Ka+œ™hN¡(f”ÈJ´%„×éw`ÁcÌ3l}M¢§3›YÚ@ó’|î@ ÒΨ™4e*?%Š•ÎLa¦ìSÓ*Õ"jœ™SȬW¨,|kqeÌÊðY} Àèa£±gXýd¦bY©0ä›4O(p”± žsÍùq ½âaµ2G™ÞMNÖÃùÎ íTy¼>kŸýbaÔIò0ý ’LJ¦¦ ÓdÉà•ÂŽ±Lì©7Uô+¤Ö&K<Ųêãiv¤½Å`0¢ÊJdûRp5€›œN_'ž 5…4B§¡[±ô[W.ؘ XfXAá¬HÛðpç9ðµÏ;§Î#ÿr É öˆüEú£¾R=)M´¾Jj…:ú RQŽ©vª´•o’Âf8µª\®©¡…RI„¦T|*ßÔ‹ å¯çÉ}<Ã2d3EšMM|æë3‹ÉÑHîtz#>‰ ^^ÔFº/En‘ªJB¥ÛSGéÐÄþ’Š}J¬¨ U[+Wÿ (E¨:Þ©òTÈ*f•Eʲ¥eòº‘b ³Ž[Q.Š—¼L"¦2ã+±ŸXÔªlä7Ã‹Žžç{3Ô!õxƒBý¢6ÑwH餋šQ=.@™îNY§ßFªNU<’©Y¶¯mXù- eÂË™i8¶”\v.èÕŒ#F/3'©œLÒ k–7œÎc‡ZÃÃì8û¬€“A­!‹ˆ½tÂEq(\–ìLܧSå*µ$ZœÁSœ¬aWz¬^Ë•¥Õ¢ña|ðÀÌaÐ1¥™?LÛÆŒóWy´@Þ¦q©: ¥Ï%G»ÃóB-z†uDš"ýQÖ‰t¡J[y3$œHOz¨e”‡jmÅKº¯ý]a&1ÃL‰&ZS9y£tÕZl”7T1_SÓ½Qè<ù*@Õ¡Üh™aŠ;¡#”5Kr&`Ó†IìÅ ŠM4©(UÙ™tLÛFÃK±¬ÙBnm8&’ÎŒ‡iCƉìˆûîA5¡9ï(Ÿäd¢<µ#Ž”[K¦cÓ†iì ¢LШîUºšbÍSæ½³jºèàØr:zNÿ‡¡Ãâ‘ú%Òƒ?BÓ¢‘R(ÑD|ªH)F—0LÞ§Ú Åb™IQšn[7Çœ=ŽN'AC®)Þ`ó{…>ÍŸîÐ?HCD4R#y|§H ¤¢Ò Éw„ÏâqÅ=Ö¡cQí©‘•‡ #™ùÒ`ì4w«<±ÈÏ¡Gð4r ‡…DÞ#QËi t˜bUñ/¾šJNX§ÉT0ê?e2’¢ðí´x/<՞Ϝçê„ ±Ò†|DH¢®èò¤‹BNí,˜VMX'BSíÊe ú™äôÄ{¿>™Ÿ¯P (!ä21v‰»Eæ£y’é#T£ÂZ½1à›2N»'ðÔBjF5‰÷Œþ|€¢A óP¯t$HÒ, àŽÿH€$ɨIvÔÌúo!;ö :Q;©,Tß(¤ ] "‡&Dh"¤‹ˆãDHQ(6–'L&”“Ièõ"‹¡J.§RB]¡€ÐíèŽtS¢0mH±¤Ð¥ r4Èúl:nŸBP®(ÞÔ³ {TJâ*Ùb²G¨$@RV‰Gô²b`Õ44œO¨”BjA•1: í>ŽGµ¤ùG*€¥‚ж’C vcúLÔi¤³5͈5û"‡äUâ‹PŠ!N$+te£ºÇ˜cff@i­ø6ô‘Z";MŠHÑ]Z.F Ťªô–=²ã_¨ÌZ —44T†µ¨Û͜Ӕjt©Ôz$C´hƒ­¢oäS†‹wÊ1aFu…H§·årÙè^¼ŒC•;4,³˜ÛÕœs–uÎâaä =fÇÇ üßÄà‚$PjÒËB½ègqÌ"tHʉßS’-'È`Òú"E’°êh%Èåͨ×¶cøT…Q524™Gî‰ í'»%V„´Ú—³“Be•M)«µ6”¦òtáÔœ¡“ŸÚuPNЉÞY',„éb£ÓÁyzOWÉïm>z'Þý`ŸàTŠ€áP. iAW(3%l¡ Ô%„ÙPñ ЫÆÁ:¨DLéôôDˆˆü](¥¸TÇNštuúr‘Nµ àí=>'ÆTûìŸØú¬PU*B¨O¥ (¡ˆÔ5Ї%Pó ÙD,(‹µ2¢\TNŠQLJ)ùF–(ÔЉQXv¤-Øèw%'ú&MTàjá“â"ÙPJÊmC (vÅÜ¢Y”Q²ŠæQmJ/ÍF9(ÌõN£an ŽQÇê9­GN(ì5Þ£Äy²hQñÊ>©Gè(ÿÅ ¤°jkÕJ ¨_”O5_âªgå@j§XÜš›S9Je‰Lt©‰Å0h¥ü”¾2—ŠRêj\…Kˆ©m¥-r¥ª´:–[RȪX½K©_å+°¥p”­b•‹R² VJ½)WU*ê¥]TÆB˜²¢ sÄ‚Sÿ¾°¦tî½²–Î É™WôŠã‰Yñ+Z¢ªÀHb§UT¾ª“IQâª-åCî¨SUŸþSíê{ÙOA©àU;D§ZÔéÊS›ŠrÕNG©Æ58n§”ß‚›ÏSvjnaM¾)´µ6H¦ÂTךÝSZJjñMS*'µDR¨u• Ò¡MT ʃ=PFªµ@>§õÔýŸuSçÊ|Os)ë¥=§œ”ñZžS¼Šw9NÓ©ØÅ:Ö§UTéüíÌ™œòU–z»¿Æ´rÈSýºê°[Ž Hye,¬D~ü®çÃ"µªVi ÄåWµªÞUXêªÉ•PJ©Uª =SË*r•MŒ©—U/Ò¥¨T¨ª“µRP*D•Gì¨î•£ T[ÊŠ‰Q*ª!…CΨl "¡MT$êƒÕPdª …@î¨Õz Sý Y&+UaT«ýUyª®ŠU¿jµEVd*ÕWJªËUjª/U8*¥9Ts*ˆ…P4©íÕ;*§TÕJ™uSª[5JØ©I&º¤¦TŒŠÍQû*;õG¨ÔUZ¢ôTYªŠ‰Q8*$©sÕ#¨¢€[þ{uj­£-±£Æ2¼Ø8zÝ“ZÂ+?ec¬fÅ…l¯åæÒºmW'êàá[ +d•jÜ­$•ž ³VHÊÆqXv+Å_f«ÆUsú®U®J³¹V@*À%WªÈUUjªKU= ¥ýT“ªPäªU>š§†TéJ›õS]ªhEL„©‚Õ.J¥˜T¬*”‘R|*LƯçÕòÚ½2WêìI]+‘5pd­ÒÕ´µºVêÑYÊ«.dŒ¬kˆj°„Uýê½™Wvªæ•[ì«bhR¬œU‡Ê¯-U´*°µUZª™•P¢©ÇU/ê¤ÉTxªŠ•PΪ Õ?§²Tî œæEE¾èC8ø7ÝÛpÌi;ì²Ù‹a°^¥ñ»€×*êÞN[ ‹Mgm¬°•’‚±åV0úĤXj«`a+ùõ}¯a仆WTŠæù\v«‚un¬­«¯ºµBV”JÏáY¯+,õdv¬l•‰š°ªVоÍW*ìÅ\¼«zÕlš­6U› ²-V*¾WªÑÕWÒª­UMЍ©Tô*šRÒµ–’zÐ[YÏ 3eŠ,˜5±¨Ö*úÄ X[‹)`P«ú¥}P¯m•æz»îWdjéI\ëup.­ÙÕ¶¶V¯*Ó©Z(+²,–>ºÆðXÃëebD¬=5†2°—– rÀþX JÿA_›+êÕ|<¯f•芼˜W‚Šî…]‘««Ut„®vUË2¹WÑNò;ÁlWëÖõ>ݫۘªoӭ˳ß5Öf§¨ÒÃZ{;!f|̵U“ˆ²Ö7þŘ’»a; í-¯îÅ÷h¾*®Bó^k·áuÙ.—eή¹WW"á–[ùëx¡nF-°³ ¶–¶2ÕqZ‡ Kýhæ- 5Ÿ,³ Öl2ÌŠYs«*±dâ¬E&±Ò3êÅ·rüŽ-¿Â7DfÓ×ûšµÓNEhÄlû5›Ü36V`É^ÙKJbÐÌHÁ‡°¢¦ èÀÅWýâü»_7KÛÙz1/Uß»L—X’èø\áë”…q¬®¿ê·™æÂÛh[? byk­-a©Æ´ëÖ”ŠÑ„Z+=ª,‰ÃùHПN3̾wØÎÄmÒ¹wÇ2à­+k¶lEMeù¨Š´–Æ„ ÎÖ¦ë/e,l…±¨F,<Ä‚˜q f`ß ©€L/Ùuõ¤¾W¬²ó$^ º¡vA.¨•Ñ ¹²'ÒãS\4ë€moM­Ò·Œ¶™–É×Ùz×Ï%)Þºô'EîåÅ_3 nßíµµ²/µ¿f§¨ÓÚ)»>¬g Éñ–y2|vEºÇ”Ï+Æb;Ì8á…W0vV†ÀP—ójû¹_%kÚ¥z1/!ßî»z_Êê] šrl®45ÃX¸ö FÑ…ÑS‰ýO>—¥Øñ’]ͳ­¦t=î[Æ8¦ð|ÛÃÛ2Ë^!jË<-¤4vw@Íqƒ“+6dÎL‡)޽1•*üÄs˜r£ `ù a€ö¯óåù¾ˆ×½²õ€^gëÄíw˜®Ô5Öêºj?²æO}o}ç̼8Go6ë Ý £–oqŠŽ Y¼¥·–Ð,Ø šÅ›Q¤i]IŸS3Žfg>ËžN%3dÌsŒt1Sv#zÖXY»+`«Œ 1ù¯Öö¾.³êô]^JkÁ©wCÀ†ø^ü ß!“Ø(yÚÜ:­w@¼å‹\d+ƒ/oI­Ç‘´Û¶"öµšÕk«GAh, J³VY®ÊÙ [ c„ bŠz±&ôÂÛ˜DsÄ`d M¯¼õóH½Û׫Sëª|ïSÁäÓ»íghên\ýË•üq–Îi½—·2†Ö¼ØûæëV6iû'=¢³éfrÊÍ"Ù~›+rdäLŒ}¡1¹Æ0:Å3ØŒ»›aul#ƒ0;Vd¿¸WäÓܺz9/‘Þc»)·QNçÃܮیâp‹ ð™º#6ËæË0×µšÁ«Ri†-E š3–ntÌ®qã*dÃL‰!N±²æ/”Å'XŒ‹±a{Œ$áƒM0C7ž4ñ4ÝÖó±1tõîz-ÊɸÑG Âß:Ûªón(læ‚M­µBfœÌÒ>Z >·g=ÌÕq˜ƒ2ÍvQÞÉGY ë cV ^!Š;±ÆŽÃÞ˹2uþNšùϹW×¶áSÛíãvvmë¢é±µÁƬ4Ô$ZYKEýh!ÌñÙ›ò3:F_ Êæ>“$Bd¬v)1uv(ÂÄg·ÂuÖŽ˜MÎÍ9V'øátÛó“wsn¨Q±åµÜ–°Ô¤jH3hn¬úñ+3avd<ˉ™SÛ&ÕdoŒ€¥Ž€±Ÿlºëh]*›7r¨.6Ã&7óvð’Ün[#eAkî­gEª9´õ6”Ñhë<¸glÑí˜O2Ð6RÆÉãšvŸ®³ÒZ9Ìç*lãy\5£âo$­Ë-¶Q6kÆÂÖßZ²cQ%i‹½¡œ3íÖu”͵٘+/Zez¬¡ñ’Ÿ:½—H*ç$œ©Ž på®­½7<ÖÛ¶Ùþ›;]jÿÍL%§ 4šæŠšÐ?Yç£9f¨ÌÆÙ—:°‡G,ç Ü©޼W*ús_Ckç |µ¯‘5ñv¾×Àº÷¿^ìëÜe{`¯gUì:¼ ×’ ñÿ^7«Åíxœ¯uáj¼WÚúŸ_Hëç½|˯“õñæ¾&×Â÷ë^òkÝ{v¯iUì’½|W­*õW^¡kÒÍz2¯A•ç–¼ß×™êòñ^UëÉ…y¯Õã"¼S׈ºðÕ^kÁE}e¯§5ô6¾sW˪ù_ëá½| ¯{õîâ½ÆW¶ öu^ë×Ez¼¯Rµé¾½$W¢*ó÷^ukÍuyˆ¯,õå¼Wúñ±^-ëĵxu¯ Uàæ¼ WÕJúQ_?+æ…|¥¯5ñ6¾׿ª÷^è«Ûµ{P¯d•ëú½iWªºõ ^–kÑ•z ¯<µæþ¼ÏW—Šò£^L+È}xé¯âž¼CW†Zð“^ +ëU}>¯¢Uóš¾]WÈúøÇ_ ëà…{ä¯wî2½³W³ªö)^º+Ö z•¯Mõé"½WŸºó«^k«ÌEyg¯(5䂼|׊ño^%«Ã­xT¯uö¾ªWÒŠùù_4+å-|~¯ŠUðš½ýW¼ê÷E^ß+Ú…{)¯_Õë^½UרZô½^Œ«Ðeyå¯7õæz¼¼W•òa^B«ÇMxȯõâ¼2ׄJðG_g+ë…}D¯£ó²¾`WÉJøÑ_+à…{ä¯wîJ½³W³ªö)^º+Ö z›¯Mõé"½WŸºó«^k«ÌEyg¯(5䂼|׊ño^%«Ã­xT¯uöʾÃWÕªú]_@«æµ|ª¯ÕñJ¾W¿ª÷©^ê+Ûå{P¯e5ëú½kתºõ ^—«ÑÅz ¯<µç¼ÏW—Šò£^L+ÈUxé¯âž¼CW†Zð‰_~kîE}œ¯®õ¾ŒWÎÊù_%+ãE|B¯‚Õ諾ßW¹*ö×^ÏëØ¥zí¯X5ên½:W¤ŠôE^~ëέy®¯1åž¼ ×’ ñó^6+Žx–¯µáR¼×àúûÇ_mëì]}_¯¦uô¾m×Êúù _+áe|¯z•À×µZöS^ÀëÖ½z±¯Pµéz½W¡ó×^q+Ìõyx¯*5ä¼…WŽšñ‘^)ëÄ5xe¯€F¿×ßšû›_hkë­}I¯£µóƾb×ɪøÝ_«àµ{ê¯xuî^½µ×³úö3^»kÖ=z›¯N•é:½WŸºó«^k«Ìmyg¯(5䂼|׊ño^%«Ã­xT¯`°WáZûÓ_okì}_¯¦uô¾m×Êúù _+áe|¯{5î¶½À×µZö_^ÀëÖíz±¯QUé’½W¡ó×^q+Ìõyx¯*õ伇׎šñ‘^)ëÄ5xe¯•àŽ¼jüW_ëî}§¯¯uõ>¾‘×Ïzù—_'ëã|G¯ƒuï¾½á×¹zöã^ÑkØÍzó¯Xõꂽ:W¤êôO^€kÎÕy´¯1µåž¼ ×’ ñó^6+Žx–¯µáR¼ׂ:ðs^ +Àè¯Âµ÷¦¾Þ×ÙúË_Nkèm|ᯖµò&¾.×Ãø ^ökÝm{‡¯kuì¾½„×­Úõm^¢«Ó%z=¯B5箼âWš:òû^UëÉ…y¯5ã"¼S׈jðË^+Áx#¯Uຼ×ã ü _v+íe}€¯ª•ô޾{×̺ù?_ëâ=|¯~µï&½Î×·ö‹^Ç«×z̯Téê½)×¢zô^v«Í¥y¯-µå¼Wúñ±^-ëĵxu¯ •àμ×*ð]^kÀm~¯½Õ÷ ¾ËWÖªú}_D«ç5|º¯‘õñ޾×Àº÷¿^ìëÜ={`¯f•ì&½qW«jõ!^™+Ñíz¯>ç*¼Ñ×—Úò¯^M«È}xî¯âž¼CW†Zð‰^ëÀ•x¯µà6»þWàJû±_k+ì}T¯¥óò¾hWÊZøó_ká {õ¯y5»W´ªö=^¾+Öez¦¯OUéN½× jóÁ^nkÌym¯(Õä–¼×êñ{^%«Ã­xT¯uàb¼×€Úïù_}+îE}œ¯®õ¾ŒWÎjùu_#ëã|7¯‚ï’½ÜW¸ÊöÁ^ΫØuzâ¯W•êB½4פ:ô9^|+ÎUy©¯0uår¼›W‘ZñÝ^3kÅex‹¯ µá&¼W€zïï^«¿•~ ¯»ÕöʾÃWÕªú]_@«æµ|ª¯ÕñJ¾W¿ª÷^è«Ûå{P¯d•ëú½iWªºôÿ^–kÑ•z¯<ææ¼É×—*ò™^IkÈ%xÞ¯µâr¼=×…ªðs^+¿½wì®ü5÷Ò¾äWÙÊúá_Q+èÅ|쯘òR¾4WÃÊø!^ù+Ýõ{’¯lÕì꽊W®Šõƒ^¥kÓ}zH¯C•çÚ¼çךšó^X«ÉÝy¯•ã6¼VWˆºðÕ^kÁEx ®ý•âž¼KWÞ:ûo_bëêý}3¯ õón¾W×ÈJø±_ +à{Ô¯uíò½ª×²šõý^µëÕ]z…¯KÕèʽWžZó^f+Ë•yQ¯'u䮼WJñé^8ëÆx¯Uâr¼EׇºðÕ^«ÁÍx¯µßò»öW}Êï£]ð+Ìy}¯-µå^¼£W“jòA^CëÇýxî¯Õã"¼[׊zñ-^!«Ã­xe¯ •àμ×*ð]ýë¿=wÖ®ùuÞî¾ü×ÜÚûC_]kêM}¯ž5ó¾MWÆêø…_«ßU{¾¯rõí®½Ÿ×±JõÛ^°kÔÝzt¯I芼ýמZó«^oëÍuy˜¯1åâ¼±W•òƒ^JëÈÕy ¯5㎼i׌*ñe^(kÄx€¯á~¼'׃êð]^kÀmwü®þU߆»è×| ïk^ŸëÓMzS¯Huè¶½W jóá^x+ÎUy¹¯4uæN¼Á×–Úò¹^Q«Éµy%¯"µãþ¼wWêñ›^/kÅex–¯ÕáÖ¼2×…Jð‰^kÁEx¯õßÞ»ó×}Êï—]îë½U}㯶õö.¾¯×Ó:ú_6ëå}|„¯‹ð²¾×½š÷[^àkÚ­{/¯`uëv½Xשºõ^+ÒõzN¯G芽ןºó×^ukÎ%y®¯3Õæ"¼¼W–zò£^PkÉ…y¯!Uãæ¼t׊ñ…^,«Å x‘¯á¼/ׄúð}^ «Àíx¯UßÊ»ð×}ï]ík½-z¼¯TÕêV½?צšô³^ëÑmz¯@ÕçÚ¼ðWœúós^jkÌyƒ¯.Uår¼¦W“jòK^EkÈ%xô¯Õã6¼^׊Êñ9^"ëÃÝxj¯ Uá&¼ׂŠð1^뿽wì®û•ß.»Ý×{ ï?_tëí=}{¯©õô޾{×̺ù?_ëâ=|¯}õï½Ë×·ö‹^Æk×zݯXõêÚ½PW¨ªôé^™+Òuz=¯DõèF½×žºóµ^q+Í¥yž¯1µå⼳וzòƒ^L+Éy ¯5㦼lWŒŠño^(kÄx€¯á~¼'׃êðg^ëÀ•x®þU߆»ëW|jïk]꫼Õw‰¯b•ëú½tW­*õƒ^ªëÔ­z¯Mõéf½$W£*ô9^ƒ+ϵyå¯9õæþ¼Ô×™Šó^\«ÊåyL¯'u䮼Š×Jñé^8ëÆx½¯•âr¼EׇºðÕ^«ÂMx9¯àv¼×ÊïÙ]÷+¾wÀ®öÞ–»ÊWxJûÓ_okì}e¯§5ô6¾p×ËZù_ká|¯{õîνÃ×µºö‹^Í+Øõ{ ¯^uëv½fW«jõA^¢«ÓÕzd¯IÕèö½סzô^|+ÎÕyį6•掼Æ×—ÚòÏ^UëÊ5y0¯$ä>¼׎šñ±^2+Žx§¯Õâ¼:׆Zð©^+Áx#¯Uà »û×~zï­]ñ«½Ýwª®óUÞ>»¿W¶jö«^ÏëÙM{¯_Õë¶½k׬õW^¦ëÔ-zo¯KÕé"½W¢*ô^~ëÏ-yÕ¯7õ溼ÌW˜Šòå^X«Êy;¯%uäj¼…WJñÇ^4ëÆx²¯5âF¼=׆ªðµ^kÁõx.¯µà6»þW~ÊïÃ]ôk¾wµ®ôµÞR»Ä×wšîÝ_v+íe}€¯ª•ô¢¾~WÍ ùK_kâm|!¯~µï&½Î׸zöí^Ø+ÚU{4¯cÕì&½|W®*õ™^­«Õ5z¯OU馽)×£Úô[^…ëÐ5yð¯<ç*¼Üך:ó'^_kËmy\¯(ÕäÚ¼’×úñÿ^;«Æõxͯõâž¼KWˆjðë^kÂ¥xD¯uàŽ¼ W€zïï]ùë¾µwË®÷uÞ»Ï×xúï ]Üë»E{¾¯uµî^½À×¶ºö«^ÏëÙM{¯`uë¶½k׬õc^¦ëÔ-zt¯KÕé"½W¢*ô#^~ëÏ]yÕ¯8•溼ÏW˜Šòñ^X«ÊyA¯&äj¼…WšñÓ^4ëÆx²¯5âF¼@W‡ ð¿^ëÁõx.¯µà6¼W*ïÃ]ôk¾5wµ®ôµÞj»Ä×wêîÝ]Øëïu}¯²Õõª¾ŸWÑ*ùÍ_.«ä}|c¯†õð.½ï×¼ê÷q^è«Üe{v¯lí*½W²Jö^¾+×zÒ¯W•êš½HW§úôÓ^–kÒz-¯C•è¼ûWž óŸ^nkÍMy“¯0uå¶¼®W”Êòm^IkÈ­y¯Õãz¼f׋ÚñY^'+Ä]x{¯ Uáj¼$׃šðQ^+À=wü®ý•ßr»å×| ïa]çë¼¥w„®ï5Ý¢»®×tÚø±_«áe|¯€µï¾½ì×¼:÷[^åëÜ {k¯kuí½—×±šö^»kÖízǯV5ꂽEW§JôÉ^“«ÑÅz'¯B5è¼õתó‰^m+Ìõy¯/åž¼«×”òa^H+È}xù¯5ãb¼dW‹zñO^%«Ä5xp¯ õáR¼"Wƒ:ðG^«Àwò®üõßZ»ãW{ZïU]櫼}w~®íÕÝŽ»¬Wtzû±_k+ì}T¯¥óò¾hWÊZù_«ãE|R¯‡•ðš¾W¿ª÷É^ó«ÝÅ{¢¯q•íò½³Wµ öu^É+Øuzþ¯]ëJ½^Wªºõ+^ŸëÓ}zY¯HuèʽW Êóí^ykÎ}y¿¯55æb¼Á×—*òÅ^S+ÉÝy+¯"µä¼zWŽ:ñ§^0«Åexœ¯uáî¼5W̺ùk_'ëäM|s¯‹µñ¾×Áºø ^ûëÞÍ{ïuµîv½Ã×·ö·^ÑkÙ}{¯a5ëνn׬Êõm^¨+ÔUzz¯L•éN½×¢zô/^€kÏ…yÚ¯9UæÒ¼ÑטÚòû^[kʽyF¯&Õ䂼‡×úñÝ_}+îE}œ¯®õ¾ŒWÐ*ùÙ_5«æ|ª¯’•ñú¾4WÅ*øy_ «à…{ú¯|•ï:½ßWºŠ÷%^ß+Û5{P¯gõ즽ŠW¯êõÑ^µëÖ z«¯Suê½7×¥êô‘^Œ«Ñz ¯?uç–¼ê×›úó]^f+ÌEyx¯,UåF¼ ×Ò:ú_=ëç |˯–µò~¾D×Ç:ø»_ëá|¯uïÖ½ï×¼š÷g^çkÜ={q¯lí*½šW±êö^¾+×z̯VÕêš½HW§ªôÓ^”ëÑíz-¯Bõè¼øWž ó•^nkÍy“¯0uå¶¾ïWÛ*û _V«éu}¯ Uó²¾kWÌ ùU_%+ãõ|h¯‹ñ ¾WÁjø^ú«Þ¥{¾¯uîJ½À×¶ºö«^ÏëÙM{¯`uë¶½k׬zõc^¦ëÔ-zt¯KÕé:½W¢*ô#^~ëÏ]yÕ¯8•溼ÏWÓšúG_Ckç½|ᯚòê¾R×Èúøó_ëâm|7¯„5ð.½ú×½ú÷“^ìëÝ{Œ¯nÕ킽¥W³JöI^ë×Åzâ¯ZUêò½SW©Zôÿ^škÒÍzC¯Eµèr½WŸjóÁ^sëë­}_¯©5ôξŽ×Ðzùã_6ëæ-|¯¯“Uò¾7WÅŠø…_ +àµ|¯}Uïf½á׺Ú÷/^àkÛ]{U¯hµì¾½Œ×°:õç^·kÖ=z±¯Tê*½:W¦Jô^kÑ=z¯@5箾ŸWÒŠú%_?+ç5|Я—Uò–¾G×ÇšøÇ_ká½|!¯‚ïê½òW¼ê÷q^è«Üe{v¯lÕíB½W²Jö^¿«×EzÒ¯X5ꮽJרZôß^–kÒEz2¯C•è2¾Ž×Ðzùã_6ëæ-|¯¯“Uò¾7WÅŠø_ kàÝ|¯}õïf½á׺Ú÷/^áëÛ{[¯hµì¾½W°šõç^·kÖez¶¯TêB½=W¦Jô§^kÑm|ü¯œÕóB¾]Wʪù)_«ãE|R¯‡•ðš¾W¿ª÷É^ó«Ýõ{¨¯rUíò½³Wµ ö^ÊkØ¥zþ¯]µë^½`תºõ7^¡kÓ¥z^¯Ió†¾e×ËZù?_"kã|]¯ˆõðÆ¾ ×ÀZ÷ë^÷ëÞM{³¯sµî½¸×¶ ö•^Í+Øõ{¯_늽fW«ÊõM^¤+Óýzi¯JuóZ¾`Wʪù)_«ãE|R¯‡•ðš¾ WÀ ÷Õ^õ+Ýõ{¨¯rUî½µ×µZö^ÊkØÍ{¯]µë^½c׫õ7^¢«Ó¥|µ¯“õò&¾9×ÅÚø›_ ëá | ¯~µï~½ä×»:÷E^ã+Ûµ{`¯iUìê½’W°êõñ^º+Ö•z¼¯UuêV½?×ʪù5_!+ãu|X¯ˆUð²¾ WÀ ÷Õ^ökÞ{­¯rõî½µ×µºö‹^ËëØÍ{ ¯^uëv½c׫jõA^¢«ä}|y¯Œuñ6¾×Âø^þ«ß%{ίwÆW·ÊöÍ^Ô+ÙÕ{)¯b•ëú½tW­zõƒ^ªëä%|n¯‹ñ ¾×Áºø ^ûëÞÍ{ïuµîv½Ã×·ö·^ÑkÙ¥{¯a5ëνqW¬Êõm_kãE|R¯‡•ðš¾W¿ª÷É^ó«Ýõ{¨¯rUíò½³WµZö^ÊkØ¥{¯]µë^½c×Ç:ø»_ëá|¯€µïÖ½ï×¼š÷g^çkÜ={v¯lí*½šW²Jö^¾+×EzÒ¯ñJ¾WÂÊø-_+ßU{Ô¯wÕË׸ö×^ÕkÚ-{/¯c5ì½y×­Úø›_ ëá | ¯~µï~½ä×»Š÷E^ã+Ûµ{f¯jìê½’W±Jõý^º+â|,¯‚Õð½÷×½š÷‡^ëkܽ{‡¯n5ín½¢×³Jö=^Âk×|7¯„5ðB½ýW¾J÷^î+ÝE{’¯o•íš½¨W³úöS^Å+Ø|1¯ƒuð½÷×½š÷“^ìëÜí{‡¯n5킽¥W³Jö=^ëá5|¯U諾êW»ê÷Q^ä«Ü {k¯jµìþ½—×±šø7_ëß­{߯y5îνÑW¸Êöí^Ø+Ú…{:¯d•ì:¾ WÀ ÷Õ^õ+Þ{­¯rõ׵ºö‹^ËëØõ| ¯~µï’½çW»Š÷E^ä«Ûå{f¯jìþ½”×ÀZ÷ß^ökÞ{³¯sµî½¸×¶ ö•^Í+ß%{Ô¯wÕÉW¸ö×^ÕkÙý{ɯvuÆW·jöÁ^Ô+ÙÕ{ïuµî^½À×·ö·^ÑkÝ{’¯o•íš½¨W¹Ú÷^ÜkÛ{¯muíV½»W¶ öâ4-M bÓí ­Æ .C 1¨W¨¢àŽ/]» XK¶Â`¦!'±H #›‚çN¨±œÐ*h‚Š5¢i‚øÇZî/¢e‹^2bµÒ¥9^'Sñ Zñâ9]°Ã³`.¡ú ˆB£¦ zÜ&ƒ‰ 5Â$û0(¼n É/ –#Bþ“P¶'Ò+9¹ ?3bmwÈ“î"Ðr<ÀÁòÁÀ*©ö 9ÖsçÀ–›($$Ž3à'ŒSã"쉘±KF)ïF éW4 o®!__‡à7ÛÒðpbt ;T¯. ¤Z8'X< kØAzàŠfèËe00)”‹cb¯É¢#º&0ýßBšètŠýއ¼©ˆPdC¬£ƒà ¾M€-\æ Ñ”å€Ù%³ª  ‚'1ÀƒÔ Ò7Ø1´f‹¹dbÂ\¦Ò'y‰'rB%É0€åœ<ÛdaªVPd.6Œˆ…‰ÐáMÞ8N¬,Žº„a÷á "ð>¶¢Ø'ƒ„¯ ÕŨ2ÂÆ Š‚ÝPà®zP)Šl âï[: Ä8"H0.EóöÃgs ÍŸö0e© \Û"©âxŸŸþ%T-¹y hzʉD¬ÕáêØ]±döü(/62HôÂ+› #@ôj˜9·Â ¤<ƒ:¨@ûø.^d ÿ?‚œ#€ž¸@%³ªõÓ‚!Ô`âÐé˜ZéÀ»ãTÎðÈB¬.æ¤ õ—BŽdX˜{Ì#…ÃDˆì–xr²®ºÚ;ê!t}èW\\ÄgÁÀCNÅC¶ àßè4´– o?ïI€±¡ *– óZöŽå!å| Ýèn@tpJŠÅÞ,?YÈÂ$D-:Š‚†"pYè¸Ò!ˆ$‡ÄÛÁÍWkÞÖû…ÆoXxP!б]ñáa =8°Z ƒ^àÊ’è/¤Œ 5÷¤/`Ÿ—h%¯`ä© EXNÔ¯‘`f180°9åã‰%c&ŠP»&²+P@Š´‚Näˆ9g=ña¬ bßzßÌ…L :ÁàIÎÖö$ÀìoÐ78R éŽÑ@µs˜*‹ê ÿæ‚Yã@¸!OHÙƒÙ$`o”xQ¶7vù XƒPãB<§ØŽ'ª#HÎ8ÂSx,ưŠI©B\ÀŠsÊ»àFËa«høb3К5S3·hG)’w\ƒÒx`ã 4Öì LêÞ¨@«‡( a‚21ƒÃxåNA)³—@fd¸ ¥-SÖO˸¹¦?ÑߎÝ@pçʹˆ.tꊜBktÈŒó: íOª‰Ða]<?ð…³!+‰(DîÊÝð©n Ø§Ð2, ¡@‚²«@ ˜è%]Ö´a‚ÐyMT²ž‹[ \x ›Ê À.IFŠÈz”GâÛ#cì&ðçà‚5)‡Œ´â¿­xŸ4´#õWˆ£¡ÕQÐj7* 5vÅ¡> H€ä’/Ë:`ÞÁð36¤ Èó¸M@ »@%. š¡þlÀvkhyÔb{ÍXP|BÀ¦ù A¶Ø8¸‡^€ÐñÄÂîFŠBœiY+UHËKp-ÊSŠDLLW¸ƒ‡bi†—ê!zÿUG Aæ„Z¹àü݈9„B è‚þ“`¯%ø(.Ð 63WÀ|Ê0·fŸ(†‡ Z0xÉ‚Ëa=àA-€8qé€ÊÆ€.fø œŒUç<ô„Ä›9rÂA†‰éÛC\Àˆ*šï‰lbJPuÕ2IÌßJêèIö@•fƒº™@×.(0²ê ¯‚• ‘¤à!9ÔŽºKàe `¼FÃ4ý FŠÈ v­þÖO0®  Š~^  /À(~Z(òŽ¥%¹1oÂFq‰Ã•aðË\,€ó‰³¹ÂÞuÌž½§¤è=µ0F=ˆ“éwF`Æ%ð,W ñô=tà¨f“[|ÀUåØmäa*ýx8ÿ8 Ûœâ%¤° $­èÐÇúbù@R؆¸òy&äe½¦A^´RX“öDV€h÷¸6B  »E‚¹p‰\Ö_׆LÐ[®pK^¾j|ƒ–¨ Éøh,†R ×!‚.ù| `¤¾#Æ] N hUtÛÚU0XÐ œŒT†ÑÀxó€?¸€Ar@ ${&qº* „JTÀÎD›èåÞpdTÜS7-“Ѥ=äpëÝä2& Š}²B/Øt›êq'êA( ;î> ä1Èe š~È! ÒSg™ €Ys¨B ì’@3L j]€€¿ã Œ€P€8 S˜º;€8(… I‚y8ìD‰ðQ!XDHg»eDjÓF›lO¢T@.ç‚„UèÚ¢2,iYïcaÌà]JdôÍ`Ó(0,RÒ ]åû¾kŸ¨ݨÞ±d 7§è ¦žgÖ~™À6xí¶éã€(;À ‘ë˜hÄ™:1#ŽÄH3½æODoëñÕ¬Eða^ ÄSÂ1"ŒCÂ{åäD6A9øIvã–Uþ¬€cØ^èÀj<$µc†þAZypD ‡E¸‘à|Õrà/2“ >Ø g¾vÛz `v¨ù·àI“£)æÄ}q?¤Fd?o8DRô1¨äD)yìSÄ4± jôBs½‡zDë1 L@pÁ­Ä~ø9…—DWv’)œi H˜³˜ À¦€ß¡)í"ôU‚=Ilð ÃZ„ÎoÙ Åe²#hDšLñ!zœG%_ˆøDTýÃã_°÷‘Ä=ŸÇT¡ÃÑðpó‹Ì<¸ #GÃÅÞðËü<ùoü6°îs,;ëƒkà ç™›Û°–qˆk«‡£$ºØ@Æ~y›ž@ :üF†•ÇÙÄ º°û¨ä=›}!"C»h°ì£¬:£ãCž,0æ«ä9s/OëÃ’Päl8å‘6,CŒ½âûÄ8º§,„CŠÜpâ¥ì8©{)LC‰…â>ì8»"ÜC‡éáúD6üTƒ ¡„]Wz<„}ìB(ŠžýL*C úúÂϤ·ˆ.x; ÆÓÂù|0À„\0Œa 9 C“PÆT1ù) OC(lpËœ2þñ ÎÁÃ7¶Pλ”3Þ yCCÈPÑÀ4šï 0cÃNÇÔ´5­ M[CTòÐÕ\5q ÄC2©ôÚX˜n²dã®Â: å¶øÿ-½@™²PFœT3•ÖøAç¡°ƒÕ"ü‡ -£ÂcÑpž ü(•ç dÆB¦ß­#\+ô &÷ÂÓªp·!.@q ®&Âó 0¾Mä/Æù þÃpÁR\0 )ˆC °ÃÞ¬1K Q:Ã/PÆü1Ÿ oEC 0È$29‰ ”ÒC&‹ÐÉçœ2“§ ªGBÅsP²€¤,é ILÂÖж¨ô-Ý» †tBå^Pºl.¼å ½+Âñ´ð½;&“P¥ º±”F³¿ú¯'ŒiXKC_ÀÚV¸šç.T󸫜òM×=fH„ƒéôºüVR¿xÒóÌ#ÿCEa¨@7ËÐÜŒ9¿<ñÀ¨·0T z}²NÁö0Dï,[SÞ¶ÁG€ðUæ4aKÑ/ÁùÐc¶l·OžA²†or„µH²AÛÔpy<ÄåeÛ®Aþ÷Ò ð÷Y5BÏð‰!$"³“Ç·B8‘$>e %BNå”Ý4%# tsBa𰙎Ô&¬« ¼UBrÖÈL'®) úB‚ oÚÚ[ùTþòº¿àäp½4?)ÎÀ^kpü "û¦@¿È°5`¤•»ò®A_pHü“ÿùAOŒðW_Ü·!ãlÁ„í0dbÈyŸ.A²ÊÐo-Ôn‰BBAÙjpx¢D©OË–Aû60€®4 ŸmEåB-ð‡ÉÔ"]½­÷B1©°l#Ê… ñBFÙ’ëd% UUÂY —‹Ü&#W šBj…ð›¢ü' ˆ³2[®™ (£,pîÓ–­6Ø"‘{ŸhFì•Z¼¶:†ÙO<øº>ž}¯´Ãûðd¬üÍi¿_WoâKúÚ˜ÿEW¿ñÊP~„êÓ+[Àe©psL V{¬†@ÀÛP5ôsgæàÁ âÐFò,±)è^ÁIðU¡ŒCAÂ*Á|á0b+œ?%z³Á©glÕÏÁjAÏ90vô;¢ÑAðÀP}ÿŒüWûB sp„øÔ! ëÔÂ%—0Šßt# g×ÎÂ;Qø$O %BN”‡d%jÍ jËB^ýo{L›âÌ>ùŸ>ž}¯´KÓð ŽüµÏ?V8ïßX{ú"ÿ ?äašäö5çÄ@T:0T2©e¶À­Ð00Œ¬ KI›ÆÀø0B4‰ DÁ6VpQCx#Aj°]‹$0¬A—*Ph4Œ«íÒ­Á½@°q—Ôó“\ÁßQyÆåe×cÁüHЀЌ ’=PBõð†·$"é—oB+90ŒD#R[æÔB>‰Æ$zy .¶,¼:kÀ*ÿ*Ç c³ž+íZy»q ââí9Ç Î¶9S¼Ìò2=,X]Ë{Û´ì÷쓾5Ï›ZêzûCª>ýµÉô{ôóøýÒ¿—ï¯î*3ý|\ÿÔ @, ÌJ»tPÀsWP"Ut Û…Ä ÀÄP5qÌsgÜ&A!pE‰¬EßÉAÁ?¹°S&d‘âÁpа^À$[³@ÄA™ØðhñdÒÖøA¾˜q¨üïI\ÁÞƒypDÃË–Aùš0à4 ZÁ-8B4°…¤|!¾õ„Â& н"ü‡Ñ_B8çLk«¾Øì»ú;›änÿƒëŶnòÂȼÿRBëØ×÷4 ¾À/óÃç( ú~>ÐaO¿“ò<¾ý(›¿mÓOãÖ›úôXÿ4-?êŒPFŒñéÝ ÀN˜0H¥ :Ì@¡¾P-!4 _?\z@ç¿°=Âd`íQA"8KùœÃÑ$sÁT`ÐX „²ÕןÁ€¢b’œ?%uVA¥êÐk±4yëþªÁǶs½$c't¯Aã›°z”¹Ú›Áü€ }5ÍÂŒ…úT!ËÕ‡WÂ&e0нà*r½ÕV1ÉÌ©.sDC2×E½·=$Ž!m«‘¶æ™Fº)5î¨zC± øíéu;ÙÙï T#ȇhó^Z=ïOXæ[Ú!„÷u|¾Ï’*Cç—žú^>Ò†¾Òãòhýq?hvâKú|.ÿØ?à[þº<=«± ÀB†P2d× '@”™°)¤Œ ˆ«#@ÙCÐ:Dtå;AxH8Tà]çLAEäðTJ<ÆÍœAqð^â|S:TA—³­Õ/Ã'\â!•9HÎf²C¡sÖê,r:ö!®×%㻚¢ðKí¼cü/,NãÏ–$ôñÁ½z!Om|[ÞÊø…ÿ¾QÇ Ë걎ûSÂ>úÂOÈ$ûô2ÚýŽˆ?ƒHè!;û×Êÿ_?òð{„ÕàAÀM@ðzS"@™öð*ê´ Àw/j@Ûi0:yD†;Aî°Gó¤ÂR·dP¯ÒL`‹O*Íf4È*-^³bM Û&(·híÿ“ˆ±>äLC9S.‚0c§gV럻A;Îç“›¿,ºñi¼Ž¡Ï5\SÑ{õYÓ½íÏr «ßºäø³¾[o¡¸ËêþÌû[D¾ü^Oǽûô†ý€•¿~¹/æÛûh6ÿEW¿é¾p‰´†¡¹¢@C°ÜŒ§ÕóüÀŽ÷°'æ< £þ@ÏàÃPºÖž_6J"m¹J£w± à ¾¸çîCö;˜‘TçìNºeJβß²•Êî;Ö¡ï _SÇàòÖ¼öøOM*KÖܪö–S½Ù‚Š‹ã€|ù‘%¾S/­03í¤ÜûöÖ?<¯ÏÉëõàýêÍ?—!¯ìZ³ü®^ÿ‹?ú¤0\aééÀMÊP5\,ß.ÚÖÌÁ›9(Ê—³ï,%^#SPþ×Oe¶l2í¿ÿCxÌÞàK¨¸•E.C;˜tç¿?:WXN®O³±Sìí¬M»½ôψcÅ>Dò[ɼØdE[Ôï$öo½¹)oz9óátêù ¾lUo¥ë•ûv>þÈ/È«óåšýp}¿w¿ïäØúÉlÿ"¿Ý#/üÙ”–Mx/À2)ÌäuSCÓ3øµeœMChÆ(ÜZ7žÎ‹ƒ‰Œä8ó¹}HyΣ¤£:ꤛ»îîÕ¬;ºe¤ïì<9Ïå«ËìóÞ½0£/Y´[Ù Æ÷*b½øvO‰ £äàdùÕϾ›¯‰î&üÈ¿ دÏtõ¨8ýØ¿(oêF‹ü Jÿ_2 ¥ ©¦›3êôÏWØ4nO@uCY/؆ˆ¶ªm Ë™zözव8žíC»—‹Šç~ߺ>«.¦ÞC¯Úí „;‘nnöÌKÂñ‹¦< šO7<óÑP,õ+±=}kycݯRøÛ>/ûÏ•ü»çÜHú†Ö¾Ä ¯¹ÃðBXü†š?>ãÖmc÷H~þ4Ô3„°­P»JC’Ô̽5»µýËl`ØÝw7¿:Î #Š<äC®9vN®uü+£XÈê9R:âHŽÌ|{·áêï¼ ªÏöÈ‹²óõ¼ú¹¯L£Ö(löJ'=¿ÞzÔkáJøò\>aV/¡t#ê‚Xû%Ÿ¾è@oÁµ ò8tüüž´O2m6f[UûZ׋z¶cXí¸7ûuzß6Û8>ç.*k‘âåÒË9Ó¦‹Nû¨(tëU¢»"®Û³»/XïÙ!<5P¯+ʹ˜ó=ãoRBëׄ ö˜y=ÐO~¦ãâJùY>jþ£ˆCêéXû:>ìFmB"kX¥´Ø‰6‚1M¾…›vÒxßy_¸I],(;‘OåÏ“9În‰nS§’@ë#5»ú.×7 ºÐﲯŽz忌×Vè6HË-®Ã“r@ÞI¿·ú=M“‹ÜXäjM¹rnr]3¡§Vé¤0º´jî¿$k´ &î Ê;Â?nÿa“Ãòñ»í¼£ÒO5K#Ðd"ôÏl½`êÏbŽKÛ4,÷hœ½ÿ´-™Æ“mLàÜö··£ß ë† ãÕ¹ýn] [œhèW˜ºbœ.ªÓ¯pìÓ”»t»nìß»¾Û0ðw¼\¾/$1ËÌ*ªóɤ=4Rî“×Y öw6½Ä(­¡8nÊÒÝG.·µ’îC㇠¬ã,»9!n]OœR èH“:[玨òk®‡<ì¥r»iwné@»½órðZóè(cº=˜Ž/`3ˆ0äÇ¥9iø.h+ëmÞè+›º=Ý.1…‹ózäÞ,¹oUni ‹êè0ø¹ºNO\s—5¶æŸ¶¹Û(ŽC9c”5†åߪ¹«jNRC—ÃTæ»›¹NW®`1+•7}d€ÌP»˜À Ý@ÚØÇ@âø´ˆ¿ÀÀظ¸­¸ºP¨øÀp™`ª@ª¸ÆØ£¾PΠ¢˜²¸H³Ð´¸½XˈÈР°´P¸®8©˜ à¢8»¯À¬pªÐÉ0ºÀ©p‘˜‚  °@ `xÁÀ¨˜©¡¸²± ©X˜ø8ƒØ|`d` 0$è$àÐ(8X¾ð·È·®Ð¦“ˆŠ€‘@ƒP‰HtÈOÐY0`Ð!ˆx#x&˜'h&`ÐX(À°h°(¯8«¨Ÿø“X•@‡@|¨€ðrèg¸i`È{ð[àOr O84˜*@A°BH1@$@ø%0È2 *("Øpp €&@¦ˆ´Àœø§¸—ø«X°’Hyh„0†XO@a°i gXbyp‰ès¸oÐO@Fà?¸98;Ð4/000*h%x"È"Ð%è'€$ð¶µH«ˆ ‘˜®•8‚°œx‰0DMNXk`N(_x`ˆ\X``U¨HpG?pGè;€0Ð+p*p--ˆ,*)°,/Í ¯˜™Ð”¨œÐ®è©xˆ@–ˆŸpQøyð|èp`\_èM`QU U0D NX7ð/(&¨0:5Ð1è.+*¨.˜8(>ˆ¢@£Å³„¸Pˆø¤øPYÀÐiørW`eàUÈHPN€U7@;È3`0Ð2¸: E3 $Èð!Ð+Ð8à<`1 _¨ÍªÀ•ø¹ð •P|p0n8cxn8^¸NxT˜PG`GxMÀB°7È*#(h$ø/@ˆ`à Ð"P(à(@°v0X Øc0Œ° øª0q°^°sÈm`u¨`€b@[XIàXhH8E˜JˆBˆ7°20 8¸ Ð;70!È'p&ˆð8h(ßÿøfÙ ˜Éø±`ªèœø‚€thp˜hàqpq€`b€N`N`THKHÀIx21h(Ø.'7ÐEp*à%hø(HˆHçÿøåù%€à¾¯¢ðxŠðuP™°j¨ w(\ÐXXMhS0FO8?¸=ˆ6°>€. 1 +(=ø1`/.Àè`èpˆ.qrp xf¨zpÀ`С‹Ø•ðƒˆtøjøjxeZ°Z¸F ?D8>Fà5 =¸?à<(8@5è@,Ð$1%ø"8#p€xF`²à¨Q5h§°˜ ˆÀa€˜p¨]¨v0‰øz0a f°nàRPWø^(Q¨LDÀJ IðA@<˜?06 *p4h+Ј'Ø'h*ø78#øÀF@ÂAUE€r(ö@ixt¢Ð»8n¨gkˆa°„P„˜nlhoÀnaXTPX@b¨ThX S8GøAh33p-h5(0¸#0#€ €!8 ¸*ГÁ)isù ñVÉŸhÌà¬XVànèz؃€Ð‚ðe¸g8Ègp{p~ ˆuÀ[°`T(U0@ðJ E8FÐ8è=°6X<Ð7&Ø+ø+а `%kæ!1±~ùÅùL9šP”`—@_a¨kÐ^ |`jÈf0hxkÈm‚@u`aÈWðZ¸VpLˆTV RøR€@@DÐ=ø9 >89(:¨6* %`80  .Ð}¹[™«ÙjQ¸èWØ}¸\0eØlOu°d`hw8|PnHw@jØe0p`epW°Q(Q¸Wð_øRðF°;ÈBA@,ð2˜58+'À%°0h2 † %I|QÈÙ5 ‹ÓØ‚‚8xÀvÐz¨}¸y \øèlÐxz˜m8jhh P¸V(bÀ^VP¨9ð:P7à3G AÀ<à;`6p9ø3#(8$À2`•9=)Ž>É„ø}¨tØg`z@mÈh˜|@THZ¸fð†ànÈx`c]xK¸[ bT H`7h:pB =˜@<(<Ð8& 5ÈD`-X`"8, %C ±y;Aqá'1KÐ]@[bX]øjj0t@|xHÐf¸u(yHh¨dø\P]Àd°Q°OèJà>°PÀLF@@`?ØHxCðCM¨FÐ2 *°/À1è: g´À÷APÇLðxàn¸o°d mÐwÐy˜xàixàrðvmXfpa8aØY`T`UHV(RX@UPE`KÈM¨IUèZ@Sø^èn¨jH\PQØVÈjh~ˆ°Ã¸´àg@gèeØt8v(p o`jxUÀ\èhb aXpb e€NNXNøPˆJðMxL˜R tÀ¡@Îðé¨ç°ãÀèà÷©.)AéHÑC‰3y Xù@ë ßÐáâä èÈòÙ)a%¡AU_ù]¡VUq]‰páŠñŸÁ¬®é¦¡—‡Iu¹e‘Z!K¹IH¡KNQT±]él}€là‹¨t¨Uøa(yHxPyxf€< ~€kˆ\(f LxFxY8ZXHRÈu0–À¸ÅöA ? Zñv‘“i­Á Ê©Çy¾ ·I¶±¿1ÍÙÚ¡ã‘æ¡åYá1Üy×!Ï™Ç1½i¶¯)ªÉª1ªa®!³q¼±ÇÒA!É3áD I¹SanQ“yº¡Ô‘âyíÉúÒ Ê R‰øIóqõ9ûQÿiÿ1û™÷¹÷qûò" R ‚ yü)ôÁïëaêÉë±ï‘ôÙû(rà‰Èz€qk(vèx°e8xГXhˆvpiXNPRˆ``Wh‡IX1ŠQ¥ñ¸qÉ‘ÕqÛ±äyöbú'b/ê."(Š%Ú%B!ºúÊ ‚ "’J¢qÿú)ý"’*!j'ú(2#ÂÊ* Ú   ò : r ™sáÆñü"’B!j(j0Â4º3‚5r<ŠCòDŠ=j3R)’ú: ÚÊ Jzb Ú9ýQû2Ê â#"'’&Ê"ª’¢brŠB:ò €~pÈŠðvXh ^¸o¸tiX}ƒ˜{ {pijzˆÅÑ-9„©×Jr6*CzEòBz=">RE*F2;Â.b):+Ò/š.b&Ò* áÿõAñéõ9ü2ª‰ÿ1ú÷øÑÿ²úêRRbJòª*ªŠ z¡ÿé_¡”ÁÜZ¢@ŠH’A²;új/*.š0’-‚-.R) â  Ò ¢Ú1û!ô ïIíéî¹î¹ìAè©æ!æQèáìiïQð‰ðïÁïÑòQ÷qÿ¢ ¢êúzú:z êá1«ÊòF2NÂZªdXCb:B4Ê)¢#R( .z/B+’%â *ºRB: š Z ª ÒÑþYúAøYöAóQïÉíií)íÁîíaë©é±è‰éAìaòQúR’ J‚*úr²2 ¢ aàrh@‚ i˜£`„°ht¸}ƒÀrБ²q‡ÁóJN2s:fJ`"j‚^ 9J#r*ª0r%RJ"(Â,z%Bb)Ú,º%ÚB²ª"ª!šê RÑÿòŠRaþQúéö¹òîÙìÁì‰íáðQóIöÉúÁÿ2Òz J j¢âª‰8 „±æ‚/¢hòn‚R:PBMÚ0 ’š)Ê"ÒÊ#z%ê‚¢z& 7*>²9b0Ê.Ú3ò81º!’2Â: ª"ú Ùüó‰ï‰ñöþÊªÚ ÿ9üqû‘ýªÒ ššš€n˜G¸r€”@fXv8‘Ðw@’ ‹˜¿`âÉ|ËiîRz5J[yB…êz2aêOÂ>:#‚ ú¢ºj+â64ª+J#‚"ª$#Ò&z02?2KÂNòJÚEA ;J/z" š²"*ºj Ñýyóññéø*zÚbꊱù!òqñÉöþê ’bzzÒYÙ6QDAsἡøj;ªn2s¢jRdÂu²ˆz|haS²0 Ú:.‚*Â'ÂâL:aJ\ÂAŠ/B5EªIê>1º5 FZUjRê?*&JÒ!R+r/:, %R’JJÒaTi·IòR!rOZWŠ:ê@B`ª_@5R="GJW’SW‚nbfJGº:ZG"TâWreòÂ…²oÂX:P’S2QrIŠE:IºPRNºBê5J127<š7b'âr r  *:6øƒàyà|°•нÛ 1!‚YÙb0âHŠXb‰*•2mê`²n*Wr.ò"B&Š#Ê+z5‚7*O"`Pº<ú8âJ_Rm‚}ZŽ ‘⃒i"QBI"Qj^cb`jZºVºP:Dê6â+#Rq%éyñ*< ƒÒl‚†ZŸš‰jwyzeâDÒ8r84r-’$ò 1Y WjEêBZF‚RºdZtú∈‚ oX²Qr_ês¢yªoêdòaR_’Ur@Š)¸>zÈ€ø¿ù ý’Ej*"”ú~*€R‘ÊŽÊjŠzÊ`Š^2Tú="5²0BjK‚j²T:IjPjS’ZjB|B€’xZsJtzn¢aÒ]ji x:zêoÂdŠbBbrZIÛb=²gjuÂ…Ò†ú{z"ˆ…Z‚¢*–Jo*dÒj¢Lº0¢3ª)2 *"ú`ri*TšVš\Z[šcRwR†²~riâb2išm¢fŠ_RbbiúiÚ`2W9B)¯ZRWòd"dúu‚{út zÒ„Ê}:|ª˜Ú«B‹šbÂaº_ÚB246Â":ò2º[RYRU2YšYÊ]²mÚƒjŠšx2_rZ²gŠphÂ[ TòVòV:W ^â[:i¢{vÚxRƒ*yŠljx2˜*¡ª€‚_r^X2AZ/Z&jJ J?ROÒPBN²H KŠ_Šw„ò~fRJUrhbsÒkjXšLÂ]òcšz‚ƒª{ú}Jr*]bY*gÚ„¢’‚{ªcJ^jQÚ- * :š7ŠGM PŠDb9’LZlÊ~Âyzc2KbBN²ebrJjzZÊyê~òxúkÒOCF’Utª…’xh"^šBj AïÊ Š;BLjH KLúBòK¢l‚„‚‚jj’Mª<Â>MŠ`‚]Je²iZS’:ª;"B2Tbn¢xzriŠY¢3êª ’BªhJ\ÊDR<‚> PRxª•"•2ZfjQjK²Q"ZZ)âFz[2I‚<òAÚNarjÒiBhZcšSª8B, Q"…ÚRg:9* B.jhªŸR¥}‚o²i’lB/MRDB@2K2bškê_rY’_ª_zWªQ`â‹B¨R–Úa‚$*/ú„ò©º“j{âwZw¢yª0r1ò=B\Bu’hšS2WZcÚfziqj„rœª¢J‡ MÊ aýEz–Jšv:izm’kbšjEsz{ÒbêX*d’m¢t‚z‘ғ"ÊsR8 øÿjSâš}Jdc‘äB²X€R{ši"eškp"‚âr¢Â•²Šâ„‚iê(AêúšCzdB\â_àz$’fB„pzfºeêr”"²"­Z—:‹ƒêbŠñáìR:,Š=ëº6ªt ŠJ† qšdÊhâ~¤¶¢¦Ò²†Ú{ZSÂà™àqðÚ9ý Nâ…*›Z’zwbobyâB©"¦òŽ¢~Êx2hšCŠùñèÉèÂcÚšŠ´zœò|z~‹BšÒ ZŠ:rkêiª\Aš$âbªl*«¹2Šºt:†J“â™2Rpra‚f²j:cbVBEr5*j"¨B—ªbkº‹š‘2‹ xZcšcÂrZ|Š~2vJeêu*«"uzKúpBŠ2Juid²qš†š–’œ*’:ÔJéR€ªSJrzy‚jbbrbªlš —êª ­ó¥3bŠ¡ŠU²a’bÂZ’Z‚d*v‹Ú :®¢­“ó®Rž*B‚KâW X2\JkÒ’’žª¤TúŒuú4HÂXê[‚còyŠŽ*–B• ”‹*ZŠC SÊY*\zoÂŒ› •ZÁ:iò`*VbNb\ºúÚ¡r‹BljFB>êabâ§Bœâ˜j^j.ê8šm›š£ÒDê"*?’{jÂ5º(R‡Ò>Rkò^ú…a8€tK!t¸V­•jÂÙRžJ£VÊ”êIZªS‰9øìpT'SÙÌØe"U)Ä‚ôp4KeQèø€B"*“ˆô!àÜe.•Ê$²0Øn9Äâ=x6˜ËeBi„=†ˆÈf5ŽCÄê=w6‹%Q |9Œ…âÑX¨T* …B¡X¬X- Æ#! ØpŸG ŽÆ³ `žG †ƒh¨P&‰D¢Q(˜L&‰Å¡X°\0 É$ØÖ`+“ˆÃá¸ÄX(ÄB€B!ˆ„B1J' …‚á€É.†;šÌbix4 ‚øt8 ‡Ðèx>DBA0 T,§G£a€ªL!ŽÆbÁ(€: †áp¸`0 ÃaÀèx@" Å"±j~7˜ŠÄ²äb*‡ƒ!p¨P& …P°\0 †ÃáŒL()Òh‘®L Ž‘p. ðx<  ÂP°\2bQC^šCLÅ’ip/ˆAPˆ< €Àh8 Â`Àl: ‰E ‰{5 ä1À¼L „ÁàÀP$A  `4 Á€Øx@#¿[Ì%RUo/”H£‘x˜> @€8 €à€P0…ÁØxB#C]Œõ¢uv2IÁ€œ> A `( `8$ „B`ÈpšËdÁøÌR „Á ( €`0  á  \2D‚QJìf¬Óˆc™„¤D Da° 8€€ @À€P0 Ã!Àø„F$ˆÄÖ ¡"|5ICÑ >‚Àà@€@@0 Aá ¨\4ˆ„bAŒJÐZ§‘CLŠ8‰Pp$ €@À€X4  †AшH%‰ÌUbUn.“ˆ#QP„2À€ €@@0  ‚!0°d6‰¢A2õHŽ= $¡ðÈN A``@  Á ðT.‡ÄBQ0˜NÑ[§Ñ'S!TŽ;‰C¡`€, €  `8" CaáL(²–)¤!ÈÂR"ŽEÂ@àT ` @À€P0 …C°è€F&CLUjYo/”Hcq`ˆ4‚ÁP  `@(„!  T, †ƒÐð€D% "¡`´ ƒáˆH& Ã! Øt< ‰¢a@¤T,‹› õ:Hüm.“ÈCaX„2ƒA@p( €àp@$ AÀð€D$ …‚áÐl:DBA(˜P) ¢áx Àà€@$ ƒ àx@" BÁpÈh6"! ”L(Š…‚ÑpÀbÒ\¨‘dzYpœAŠÄA ¨H àp8 P( ƒáˆH& …ƒÐl:DBA(œP)‹¢á€Äd ‚A H$ Á`Àh8Ba@¨X. †ƒÐð€B" DâP¬X-Œ#1£5j FÍeÒyn,CP˜@ Á`°P, ƒ€Ðh8BA0 T, †ƒaÀè|@!‰¢q@¨V, Æ!˜Ðj6 Aààp4  Ðh8„! L( ÃÐp:ˆB1 ˜N) Å¢áxÄd3 †ã‡35l¡FŸMÅò‰r/ˆCÀX* „Bðx<àð€@" ÂP¨X. †ƒaÀð|@!Ä¢a@¤T,‹†Ðj6ŽAÐØh0 Ba D ˆH$ ¡`¸`2 ‡¡àø€B"‰¢q@¤V,‹Æ˜Ðj7GC±ã© ¹R$PPŽ; Ä¢1|: Cp¨P( ‚A ˜L& …BÁpÀ`2 ‡¡àø€B"‰¢a8¤T+‹…ãÌj6Ž#±àô|- Ä¢1|< †ƒ!€¸X* ¡P¨X, ! Øp:ÄŒH% Å¡X°Z/ FCA¨Øp9ǃÑùïj¯TéDÌÈV$†Ã1x°T'ˆÄ"øt8 Cp¸\. †Èh6CÁñ„D# D¢a8¤T+ EÂñˆÈf4 Ç‘Øðz>$"¹@”E Q¼X* „‚!|<ÃAÈd2 ƒa°àt:ˆ"!ŒH% Å‘P¬X- ƘÐj6GC±àø~@ ˆdHƒÍ°ÀU¥ÐÇSi˜¼X(“ä!ðìp4‹Å‚¡@˜J#áàèp8 ‡Àèt<ˆ"!ŒH% Å‘H¨V,‹…ècñØÜg0JdâI‚= ƃx°T)‰D‚1€>ƒÁàø|> DB!J&Š"‘TÊ(÷n1ÊDÒE;›ÍÙT K#ÈÑÈØh1‹Eb‘@˜J$ˆ„"„B!„B1 J&Š+¥‚•6‘D çIˆ¸W)‰Dbüx9 "ñp°T) „¢Q H$ ‚Q(˜L' fчێ»X©“‰$Jðq5 Å’©@˜I"‡ãÁÈØh2 …¢±P¤P'‰Äâq8œN( E-FBõd§N¤ÑHÉÈØf0— å2y,D ‡ƒ‘¸Ôf1 …¢ÁX¬T* …B¡X­üðqµY+å’¡:”E gCq Æ^-ŠDâQˆAC°Ðd1 ÅÂáh´Z-‹\mfRùf¨O%QˆCéØàj2˜K…‚¡DšJ#‘Cñèèr7c!ˆÄ`0 ì¥úÑRŸK#PÇóÁÈÚh2Ëer¡@šJ#‘HDèìt8†£Q ÐhË_­Jº==N³1ˆ¼Z+ÊÒQŠC ‡£±Ðär80ªµe"ŠB3q¤Êa.–JÅ24”H"È$øøz<0VÊÅ"m(C Ogc‰°Ðd0 %b™@šK$ˆ¤2€·W)“Ét‚)~< æ³9Œ¾\,•Šeq0”H#‘H‹•‚¥BšJ#PèáÜän5Œeòád¬T(“ɤ²Q%f«R'’éZþz:œM¦“1ŒÀ]-Ê¥"=l¯T(SiDr!~<ÃI˜Æ`.–Ëb¢åd«R§“ $b|<ÓQœÈa/ +Õ²½P¢M¥Qè¤*öw9œ ¦£9Ä_`.VjÅ*}2“F¢góÙÜèq7ÍeêÙ`©Q§Éb~=ž§#y±€ºY«TÊÒQŠC çÃÉØæÄ^­Ö ¥u0“G"È3ùðôÈ`®–ŠÕ:…6–I#‘Ht–Ä_-Ö*¥"}4–I#‘h†{!‚»Z+• 4òi,’G£LÆ*ùp±V)”IäÒY&Ög²XKµª½T¦Q'“M¦›1Œ¿\¬ÕÊ¥2‰®Ðd°×«u’¹TÔf±Ø+µºÉ\Øi2جÚݬÏd±í¦£9’Øi3[­w€ @ @@ €@ € P €@ €@ €@ @ €X @€@ €@ €@$ €€(€@ €@  ‚A °€@ €@  ‚A H$ @ €@ A H$ ‚A °€@ H$ ‚A H$ Aà@P €@  ‚A H$ ‚€@ @€@ A H$ ‚A @   €@  ‚A H$ €@  H$ ‚A H$€@  €A H$‰D‚A €@ €@ €@( €`€À`X$ ‚Q(„@ €@ €@ @ P€@`0‚A €@!ˆ€@ €@ €P( ˆ`0€@P €@ €@ €@ €@ P€€@ €@ €@ €P(€@€@ €@ €@ €@ €`P €@ €@ €@ €@ €@ €@ €@  @ €@€@ €@ €@ €@ €@( €@ €@ €@ @ €@ €@ €@ €@ €@ €@ €@(€@ €@ €@ €@ €@  €@ @ €@ €@ €@ €@ €@ €@  €@ €@ €@ €@ €@ €@( 0 €@ €@ €@ €@ €@ €@ €@  €@€@ €@ €@ €@ €@ €@ €@€@ €@ €@ €@ €@ €@  €@ €@ €@ €@ €@ € (€@ €@ €@ €@ €@€@ (€@ €@ €@ €@ €€@€@ P €@ €@ €@ €@ €@ @ P(€@ €@ €@ €@ €@ €@ €@€@ €@ €@  €@ €@` @ P €@ €@ €@ €@   €@ €@ €@  @ @ €@ €@ €À` €@ @ €@ €@ €@   (@  €@ @ 0€ @$€@ @$€@ €@$ ‚€@ H €@  @ €€€€€ €@ €@ €@ €@ € €€@€€@€€ €€@   €@ €P8€€@ À`€`0€`0À`€À`0 7777metkit-1.16.0/tests/regressions/METK-89/000077500000000000000000000000001513171467200176065ustar00rootroot00000000000000metkit-1.16.0/tests/regressions/METK-89/CMakeLists.txt000066400000000000000000000002721513171467200223470ustar00rootroot00000000000000 if ( HAVE_GRIB AND HAVE_BUILD_TOOLS ) ecbuild_configure_file( METK-89.sh.in METK-89.sh @ONLY ) ecbuild_add_test( TYPE SCRIPT COMMAND METK-89.sh ) endif() metkit-1.16.0/tests/regressions/METK-89/METK-89.sh.in000077500000000000000000000037511513171467200215560ustar00rootroot00000000000000#!/usr/bin/env bash set -eux parse="$" srcdir=@CMAKE_CURRENT_SOURCE_DIR@ bindir=@CMAKE_CURRENT_BINARY_DIR@ wdir=$bindir/METK-89 export ECCODES_DEFINITION_PATH="@ECCODES_DEFINITION_PATH@" ### cleanup and prepare test cat > req < req < req < req.porcelain < req.json < list < content #cmp list content metkit-1.16.0/tests/test_c_api.c000066400000000000000000000013231513171467200165220ustar00rootroot00000000000000/* * (C) Copyright 1996- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation * nor does it submit to any jurisdiction. */ /// @file test_c_api.c /// @date Dec 2024 /// @author Christopher Bradley #include #include "metkit/api/metkit_c.h" int main(int argc, char** argv) { const char* version = metkit_version(); metkit_error_t err = metkit_initialise(); fprintf(stdout, "MetKit version: %s\n", version); return 0; } metkit-1.16.0/tests/test_c_api.cc000066400000000000000000000201461513171467200166710ustar00rootroot00000000000000/* * (C) Copyright 1996- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation * nor does it submit to any jurisdiction. */ /// @file test_c_api.cc /// @date Dec 2024 /// @author Christopher Bradley #include #include #include #include #include "eckit/testing/Test.h" #include "eckit/types/Date.h" #include "metkit/api/metkit_c.h" #include "metkit/mars/MarsRequest.h" namespace metkit::test { using ::eckit::testing::TestException; // Wrapper around the C function calls that will throw an exception if the function fails // i.e. if the return value is not METKIT_SUCCESS void test_success(int e) { metkit_error_values_t err = static_cast(e); if (err != METKIT_SUCCESS) throw TestException("C-API error: " + std::string(metkit_get_error_string(err)), Here()); } void EXPECT_STR_EQUAL(const char* a, const char* b) { if (std::strcmp(a, b) != 0) { throw TestException("Expected: " + std::string(a) + " == " + std::string(b), Here()); } } // Fairly minimal test coverage CASE("metkit_marsrequest") { // ----------------------------------------------------------------- // Basics // ----------------------------------------------------------------- metkit_marsrequest_t* request{}; test_success(metkit_marsrequest_new(&request)); EXPECT(request); // set/get verb test_success(metkit_marsrequest_set_verb(request, "retrieve")); const char* verb{}; test_success(metkit_marsrequest_verb(request, &verb)); EXPECT_STR_EQUAL(verb, "retrieve"); // set array of values const char* dates[] = {"20200101", "20200102", "-1"}; test_success(metkit_marsrequest_set(request, "date", dates, 3)); // set single value const char* expver = "xxxx"; test_success(metkit_marsrequest_set_one(request, "expver", expver)); test_success(metkit_marsrequest_set_one(request, "param", "2t")); // check values bool has = false; test_success(metkit_marsrequest_has_param(request, "date", &has)); EXPECT(has); test_success(metkit_marsrequest_has_param(request, "random", &has)); EXPECT(!has); size_t count = 0; test_success(metkit_marsrequest_count_values(request, "date", &count)); EXPECT_EQUAL(count, 3); for (size_t i = 0; i < count; i++) { const char* value{}; test_success(metkit_marsrequest_value(request, "date", i, &value)); EXPECT_STR_EQUAL(value, dates[i]); } // ----------------------------------------------------------------- // Expand // ----------------------------------------------------------------- metkit_marsrequest_t* expandedRequest{}; test_success(metkit_marsrequest_new(&expandedRequest)); test_success(metkit_marsrequest_expand(request, false, true, expandedRequest)); // Check date expanded -1 -> yesterday test_success(metkit_marsrequest_count_values(expandedRequest, "date", &count)); EXPECT_EQUAL(count, 3); std::array dates_expanded; for (size_t i = 0; i < count; i++) { test_success(metkit_marsrequest_value(expandedRequest, "date", i, &dates_expanded[i])); } EXPECT_STR_EQUAL(dates_expanded[2], std::to_string(eckit::Date(-1).yyyymmdd()).c_str()); // check param expanded 2t -> 167 const char* param{}; test_success(metkit_marsrequest_value(expandedRequest, "param", 0, ¶m)); EXPECT_STR_EQUAL(param, "167"); // ----------------------------------------------------------------- // Merge // ----------------------------------------------------------------- metkit_marsrequest_t* req_manydates{}; test_success(metkit_marsrequest_new(&req_manydates)); const char* dates_many[] = {"19000101", "19000102", "19000103"}; test_success(metkit_marsrequest_set(req_manydates, "date", dates_many, 3)); test_success(metkit_marsrequest_merge(request, req_manydates)); test_success(metkit_marsrequest_count_values(request, "date", &count)); EXPECT_EQUAL(count, 6); // ----------------------------------------------------------------- // done metkit_marsrequest_delete(request); metkit_marsrequest_delete(expandedRequest); metkit_marsrequest_delete(req_manydates); } //----------------------------------------------------------------------------- CASE("metkit_requestiterator_t parsing") { metkit_requestiterator_t* it{}; test_success( metkit_parse_marsrequests("retrieve,date=-1,param=2t \n retrieve,date=20200102,param=2t,step=10/to/20/by/2", &it, true)); // two separate requests std::vector requests; metkit_iterator_status_t status; while ((status = metkit_requestiterator_next(it)) == METKIT_ITERATOR_SUCCESS) { metkit_marsrequest_t* req{}; test_success(metkit_marsrequest_new(&req)); EXPECT_EQUAL(metkit_requestiterator_current(it, req), METKIT_ITERATOR_SUCCESS); requests.push_back(req); } EXPECT_EQUAL(status, METKIT_ITERATOR_COMPLETE); EXPECT_EQUAL(requests.size(), 2); // check the date const char* date{}; test_success(metkit_marsrequest_value(requests[0], "date", 0, &date)); EXPECT_STR_EQUAL(date, std::to_string(eckit::Date(-1).yyyymmdd()).c_str()); // parser also calls expand test_success(metkit_marsrequest_value(requests[1], "date", 0, &date)); EXPECT_STR_EQUAL(date, "20200102"); // Check steps have been parsed size_t count = 0; test_success(metkit_marsrequest_count_values(requests[1], "step", &count)); EXPECT_EQUAL(count, 6); for (size_t i = 0; i < count; i++) { const char* step{}; test_success(metkit_marsrequest_value(requests[1], "step", i, &step)); EXPECT_STR_EQUAL(step, std::to_string(10 + i * 2).c_str()); } // cleanup metkit_requestiterator_delete(it); // NB: requests have been moved out of the iterator for (auto& req : requests) { metkit_marsrequest_delete(req); } } // Ensure that the param iterator works as expected CASE("metkit_paramiterator_t ") { std::string str = "retrieve,date=20200102,param=2t,step=10/to/20/by/2"; metkit_marsrequest_t* request{}; test_success(metkit_marsrequest_new(&request)); test_success(metkit_parse_marsrequest(str.c_str(), request, true)); metkit_paramiterator_t* it{}; test_success(metkit_marsrequest_params(request, &it)); metkit_iterator_status_t status; std::set keys; while ((status = metkit_paramiterator_next(it)) == METKIT_ITERATOR_SUCCESS) { const char* key{}; EXPECT_EQUAL(metkit_paramiterator_current(it, &key), METKIT_ITERATOR_SUCCESS); keys.insert(key); } EXPECT_EQUAL(status, METKIT_ITERATOR_COMPLETE); // Compare with C++ impl for consistency mars::MarsRequest req = mars::MarsRequest::parse(str, true); std::set keys_cpp; for (const auto& k : req.params()) { keys_cpp.insert(k); } EXPECT_EQUAL(keys, keys_cpp); } CASE("metkit_requestiterator_t 1 item") { // Edge case: verify iterator with one item works the same way. metkit_requestiterator_t* it{}; test_success(metkit_parse_marsrequests("retrieve,date=-1,param=2t", &it, true)); std::vector requests; metkit_iterator_status_t status; while ((status = metkit_requestiterator_next(it)) == METKIT_ITERATOR_SUCCESS) { metkit_marsrequest_t* req{}; test_success(metkit_marsrequest_new(&req)); EXPECT_EQUAL(metkit_requestiterator_current(it, req), METKIT_ITERATOR_SUCCESS); requests.push_back(req); } EXPECT_EQUAL(status, METKIT_ITERATOR_COMPLETE); EXPECT_EQUAL(requests.size(), 1); // cleanup metkit_requestiterator_delete(it); for (auto& req : requests) { metkit_marsrequest_delete(req); } } } // namespace metkit::test int main(int argc, char** argv) { return eckit::testing::run_tests(argc, argv); } metkit-1.16.0/tests/test_codes_api.cc000066400000000000000000000254111513171467200175440ustar00rootroot00000000000000/* * (C) Copyright 2025- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation * nor does it submit to any jurisdiction. */ // Include operator<< via LocalConfiguration #include #include "eccodes.h" #include "eckit/config/LocalConfiguration.h" #include "eckit/io/Buffer.h" #include "eckit/testing/Test.h" #include "metkit/codes/api/CodesAPI.h" #include "metkit/codes/api/CodesTypes.h" #include "metkit/codes/api/KeyIterator.h" namespace metkit::grib::test { //----------------------------------------------------------------------------- // No explicit expectations here // However, we iterate the whole sample and print all keys // Keys are fetched by inspecting the native type and calling a specialized getXXX // A non-throwing behaviour is at least CASE("Test iterate sample, getting all keys by native type on iterator") { using namespace codes; auto handle = codesHandleFromSample("GRIB2"); for (auto& k : handle->keys()) { // std::cout << "\t" << k.name() << ": "; auto valFromIt = k.get(); auto valFromHandle = handle->get(k.name()); auto type = k.type(); // std::visit([](const auto& v) { std::cout << v << std::endl; }, valFromIt); if (k.name() != "sectionNumber" && k.name() != "numberOfSection") { EXPECT_EQUAL(valFromIt.index(), valFromHandle.index()); std::visit( [&](const auto& v) { // std::cout << "\t(from handle): " << v << std::endl; EXPECT_EQUAL(v, std::get>(valFromHandle)); }, valFromIt); } } } CASE("Test iterate and rewrite keys") { using namespace codes; auto handle = codesHandleFromSample("GRIB2"); using IF = KeyIteratorFlags; std::vector> values; for (auto& k : handle->keys(IF::SkipReadOnly)) { values.emplace_back(k.name(), k.get()); } EXPECT(values.size() > 0); for (const auto& p : std::move(values)) { // TODO(pgeier) Raise eccodes bug about not readonly keys if (p.first == "validityDateTime") continue; if (p.first == "productType") continue; if (p.first == "isTemplateDeprecated") continue; if (p.first == "isTemplateExperimental") continue; if (p.first == "datasetForLocal") continue; if (p.first == "isMessageValid") continue; try { std::visit([&](const auto& val) { handle->set(p.first, val); }, p.second); } catch (...) { std::cerr << "Error setting " << p.first << ": "; std::visit([&](const auto& val) { std::cerr << val << std::endl; }, p.second); throw; } }; } CASE("Test geo iterator") { using namespace codes; auto handle = codesHandleFromSample("GRIB2"); long numberValues = handle->getLong("numberOfValues"); auto lons = handle->getDoubleArray("longitudes"); auto lats = handle->getDoubleArray("latitudes"); auto values = handle->getDoubleArray("values"); EXPECT_EQUAL(lons.size(), numberValues); EXPECT_EQUAL(lats.size(), numberValues); EXPECT_EQUAL(values.size(), numberValues); long count = 0; // TODO(pgeier) Use structured binding with C++20; for (const auto& {longitude, latitude, value}: handle->values()) // {} for (const auto& data : handle->values()) { // std::cout << "\t" << count << ": " << data.longitude << "/" << data.latitude << ": " << data.value << // std::endl; EXPECT_EQUAL(lons[count], data.longitude); EXPECT_EQUAL(lats[count], data.latitude); EXPECT_EQUAL(values[count], data.value); ++count; } EXPECT_EQUAL(count, numberValues); } CASE("Test setting values") { using namespace codes; auto handle = codesHandleFromSample("GRIB2"); long numberValues = handle->getLong("numberOfValues"); std::vector newVals; for (int i = 0; i < numberValues; ++i) { newVals.push_back((double)i); } EXPECT_NO_THROW(handle->set("values", newVals)); auto values = handle->getDoubleArray("values"); EXPECT_EQUAL(newVals, values); long count = 0; for (const auto& data : handle->values()) { EXPECT_EQUAL(newVals[count], data.value); ++count; } EXPECT_EQUAL(count, numberValues); } CASE("Test load and iterate mars keys") { using namespace codes; auto handle = codesHandleFromSample("GRIB2"); handle->set("date", 20250101); handle->set("time", 1400); handle->set("step", (long)18); handle->set("param", (long)132); for (auto& k : handle->keys(namespaces::mars)) { if (k.name() == "date") { EXPECT_EQUAL(std::get(k.get()), 20250101); } if (k.name() == "time") { EXPECT_EQUAL(std::get(k.get()), 1400); } if (k.name() == "step") { EXPECT_EQUAL(std::get(k.get()), 18); } if (k.name() == "levtype") { EXPECT_EQUAL(std::get(k.get()), "sfc"); } if (k.name() == "param") { EXPECT_EQUAL(std::get(k.get()), 132); } } } CASE("Test isDefined, has, isMissing, set MARS key \"class\"") { using namespace codes; auto handle = codesHandleFromSample("GRIB2"); EXPECT(!handle->isDefined("class")); EXPECT(!handle->has("class")); EXPECT(!handle->isDefined("anoffset")); EXPECT(!handle->has("anoffset")); // Set a local definition template with mars keys EXPECT_NO_THROW(handle->set("setLocalDefinition", 1)); EXPECT_NO_THROW(handle->set("localDefinitionNumber", 15)); // Mars directly get a "default" value instead of being set to missing EXPECT(handle->isDefined("class")); EXPECT(!handle->isMissing("class")); EXPECT(handle->has("class")); EXPECT_NO_THROW(handle->set("class", "od")); EXPECT_EQUAL(handle->getString("class"), std::string("od")); EXPECT(!handle->isMissing("class")); EXPECT(handle->has("class")); // Mars key can not set to be missing EXPECT_THROWS(handle->setMissing("class")); } CASE("Test set missing") { using namespace codes; auto handle = codesHandleFromSample("GRIB2"); EXPECT_NO_THROW(handle->set("productDefinitionTemplateNumber", 0)); EXPECT(handle->isDefined("scaledValueOfFirstFixedSurface")); EXPECT(handle->isMissing("scaledValueOfFirstFixedSurface")); EXPECT(!handle->has("scaledValueOfFirstFixedSurface")); EXPECT_NO_THROW(handle->set("scaledValueOfFirstFixedSurface", 123)); EXPECT_EQUAL(handle->getLong("scaledValueOfFirstFixedSurface"), 123); EXPECT(!handle->isMissing("scaledValueOfFirstFixedSurface")); EXPECT(handle->has("scaledValueOfFirstFixedSurface")); EXPECT_NO_THROW(handle->setMissing("scaledValueOfFirstFixedSurface")); EXPECT(handle->isMissing("scaledValueOfFirstFixedSurface")); EXPECT(!handle->has("scaledValueOfFirstFixedSurface")); } CASE("Test copyInto and clone") { using namespace codes; auto handle = codesHandleFromSample("GRIB2"); size_t size = handle->messageSize(); std::vector bytes(size); EXPECT_NO_THROW(handle->copyInto(bytes.data(), size)); auto handle2 = handle->clone(); EXPECT_EQUAL(handle2->messageSize(), size); size_t size2 = handle2->messageSize(); std::vector bytes2(size2); EXPECT_NO_THROW(handle2->copyInto(bytes2.data(), size2)); EXPECT_EQUAL(size, size2); for (int i = 0; i < size; ++i) { EXPECT_EQUAL(bytes[i], bytes2[i]); } } CASE("Test copyInto and codesHandleFromMessage") { using namespace codes; auto handle = codesHandleFromSample("GRIB2"); size_t size = handle->messageSize(); std::vector bytes(size); EXPECT_NO_THROW(handle->copyInto(bytes.data(), size)); auto handle2 = codesHandleFromMessage({bytes.data(), size}); EXPECT_EQUAL(handle2->messageSize(), size); size_t size2 = handle2->messageSize(); std::vector bytes2(size2); EXPECT_NO_THROW(handle2->copyInto(bytes2.data(), size2)); EXPECT_EQUAL(size, size2); for (int i = 0; i < size; ++i) { EXPECT_EQUAL(bytes[i], bytes2[i]); } } CASE("Test copyInto and codesHandleFromMessageCopy") { using namespace codes; auto handle = codesHandleFromSample("GRIB2"); size_t size = handle->messageSize(); std::vector bytes(size); EXPECT_NO_THROW(handle->copyInto(bytes.data(), size)); auto handle2 = codesHandleFromMessageCopy({bytes.data(), size}); EXPECT_EQUAL(handle2->messageSize(), size); size_t size2 = handle2->messageSize(); std::vector bytes2(size2); EXPECT_NO_THROW(handle2->copyInto(bytes2.data(), size2)); EXPECT_EQUAL(size, size2); for (int i = 0; i < size; ++i) { EXPECT_EQUAL(bytes[i], bytes2[i]); } } CASE("Test copyInto and codesHandleFromFile") { using namespace codes; auto handle = codesHandleFromSample("GRIB2"); size_t size = handle->messageSize(); std::vector bytes(size); EXPECT_NO_THROW(handle->copyInto(bytes.data(), size)); std::string ofname{"GRIB2.tmpl"}; { std::ofstream of(ofname, std::ios::binary); if (!of) { throw std::runtime_error("Failed to open file: " + ofname); } of.write(reinterpret_cast(bytes.data()), size); of.close(); } auto handle2 = codesHandleFromFile(ofname, Product::GRIB); EXPECT_EQUAL(handle2->messageSize(), size); size_t size2 = handle2->messageSize(); std::vector bytes2(size2); EXPECT_NO_THROW(handle2->copyInto(bytes2.data(), size2)); EXPECT_EQUAL(size, size2); for (int i = 0; i < size; ++i) { EXPECT_EQUAL(bytes[i], bytes2[i]); } } } // namespace metkit::grib::test namespace std { template <> struct default_delete { void operator()(codes_handle* h) { ::codes_handle_delete(h); } }; } // namespace std namespace metkit::grib::test { CASE("Test release handle") { using namespace codes; auto handle = codesHandleFromSample("GRIB2"); std::unique_ptr raw = std::unique_ptr(reinterpret_cast(handle->release())); EXPECT(raw); EXPECT_THROWS_AS(handle->getLong("discipline"), CodesException); } //----------------------------------------------------------------------------- } // namespace metkit::grib::test int main(int argc, char** argv) { return eckit::testing::run_tests(argc, argv); } metkit-1.16.0/tests/test_codes_decoder.cc000066400000000000000000000571651513171467200204130ustar00rootroot00000000000000/* * (C) Copyright 1996- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation * nor does it submit to any jurisdiction. */ /// @date Nov 2022 /// @author Philipp Geier #include #include #include #include "eckit/config/LocalConfiguration.h" #include "eckit/io/MemoryHandle.h" #include "eckit/message/Message.h" #include "eckit/message/Reader.h" #include "eckit/testing/Test.h" namespace metkit::codes::test { //---------------------------------------------------------------------------------------------------------------------- class MetadataSetter : public eckit::LocalConfiguration { public: using eckit::LocalConfiguration::getDouble; using eckit::LocalConfiguration::getLong; using eckit::LocalConfiguration::getString; using eckit::LocalConfiguration::has; template void setValue(const std::string& key, const T& value) { set(key, value); } template T get(const std::string& key) { T value; eckit::LocalConfiguration::get(key, value); return value; } std::vector keys() { return eckit::LocalConfiguration::keys(); } }; static unsigned char unstr_latlon[] = { 0x47, 0x52, 0x49, 0x42, 0xff, 0xff, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9f, 0x00, 0x00, 0x00, 0x15, 0x01, 0x00, 0x62, 0x00, 0xff, 0x19, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x02, 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x04, 0x01, 0x30, 0x30, 0x30, 0x31, 0x00, 0x00, 0x00, 0x23, 0x03, 0x00, 0x00, 0x00, 0x01, 0xf0, 0x00, 0x00, 0x00, 0x65, 0x06, 0x00, 0x00, 0x0a, 0x01, 0x66, 0xa3, 0x41, 0xd2, 0x1d, 0xcf, 0x11, 0xb2, 0x88, 0x0c, 0x0f, 0x16, 0x45, 0xf3, 0xd1, 0xdc, 0x00, 0x00, 0x00, 0x22, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0xa8, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x15, 0x05, 0x00, 0x00, 0x01, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0xff, 0x00, 0x00, 0x00, 0x05, 0x07, 0x37, 0x37, 0x37, 0x37}; #define MD_EXPECT_STRING(md, name, eq) \ EXPECT(md.has(name)); \ std::cout << "expect string for " << name << " to equal " << eq << " (got " << md.getString(name) << ")" \ << std::endl; \ EXPECT_EQUAL(eq, md.getString(name)); // we accept two possible encodings, to enable testing with different versions of ecCodes (ECC-1704) #define MD_EXPECT_STRINGS(md, name, eq1, eq2) \ EXPECT(md.has(name)); \ std::cout << "expect string for " << name << " to equal " << eq1 << " or " << eq2 << " (got " \ << md.getString(name) << ")" << std::endl; \ EXPECT(md.getString(name) == eq1 || md.getString(name) == eq2); #define MD_EXPECT_LONG(md, name, eq) \ EXPECT(md.has(name)); \ std::cout << "expect long for " << name << " to equal " << eq << " (got " << md.getLong(name) << ")" << std::endl; \ EXPECT_EQUAL(eq, md.getLong(name)); #define MD_EXPECT_GE_LONG(md, name, eq) \ EXPECT(md.has(name)); \ std::cout << "expect long for " << name << " to be greater than or equal to " << eq << " (got " \ << md.getLong(name) << ")" << std::endl; \ EXPECT(md.getLong(name) >= eq); #define MD_EXPECT_DOUBLE(md, name, eq) \ EXPECT(md.has(name)); \ std::cout << "expect double for " << name << " to equal " << std::to_string(eq) << " (got " \ << std::to_string(md.getDouble(name)) << ")" << std::endl; \ EXPECT_EQUAL(std::to_string(eq), std::to_string(md.getDouble(name))); //---------------------------------------------------------------------------------------------------------------------- CASE("test codessplitter unstr_latlot.tmpl Native") { eckit::MemoryHandle data(static_cast(unstr_latlon), sizeof(unstr_latlon)); std::cout << "Data location " << ((size_t)&unstr_latlon) << std::endl; eckit::message::Reader reader(data); eckit::message::Message msg; msg = reader.next(); EXPECT(msg); MetadataSetter md; eckit::message::TypedSetter gatherer{md}; eckit::message::GetMetadataOptions mdOpts{}; mdOpts.valueRepresentation = eckit::message::ValueRepresentation::Native; mdOpts.nameSpace = ""; msg.getMetadata(gatherer, mdOpts); { MD_EXPECT_STRING(md, "globalDomain", "g"); MD_EXPECT_LONG(md, "GRIBEditionNumber", 2); MD_EXPECT_GE_LONG(md, "tablesVersionLatestOfficial", 30); MD_EXPECT_GE_LONG(md, "tablesVersionLatest", 30); MD_EXPECT_LONG(md, "grib2divider", 1000000); MD_EXPECT_LONG(md, "angleSubdivisions", 1000000); MD_EXPECT_LONG(md, "missingValue", 9999); MD_EXPECT_LONG(md, "ieeeFloats", 1); MD_EXPECT_LONG(md, "isHindcast", 0); MD_EXPECT_LONG(md, "section0Length", 16); MD_EXPECT_STRING(md, "identifier", "GRIB"); MD_EXPECT_LONG(md, "discipline", 2); MD_EXPECT_LONG(md, "editionNumber", 2); MD_EXPECT_LONG(md, "totalLength", 159); MD_EXPECT_LONG(md, "section1Length", 21); MD_EXPECT_STRING(md, "centre", "ecmf"); MD_EXPECT_STRING(md, "centreDescription", "European Centre for Medium-Range Weather Forecasts"); MD_EXPECT_LONG(md, "subCentre", 255); MD_EXPECT_LONG(md, "tablesVersion", 25); MD_EXPECT_STRING(md, "masterDir", "grib2/tables/[tablesVersion]"); MD_EXPECT_LONG(md, "localTablesVersion", 0); MD_EXPECT_LONG(md, "significanceOfReferenceTime", 0); MD_EXPECT_LONG(md, "year", 1); MD_EXPECT_LONG(md, "month", 1); MD_EXPECT_LONG(md, "day", 1); MD_EXPECT_LONG(md, "hour", 0); MD_EXPECT_LONG(md, "minute", 0); MD_EXPECT_LONG(md, "second", 0); MD_EXPECT_LONG(md, "dataDate", 10101); MD_EXPECT_DOUBLE(md, "julianDay", 1.7214235e+06); MD_EXPECT_LONG(md, "dataTime", 0); MD_EXPECT_LONG(md, "productionStatusOfProcessedData", 0); MD_EXPECT_STRING(md, "typeOfProcessedData", "an"); MD_EXPECT_LONG(md, "selectStepTemplateInterval", 1); MD_EXPECT_LONG(md, "selectStepTemplateInstant", 1); MD_EXPECT_STRING(md, "stepType", "instant"); MD_EXPECT_LONG(md, "is_chemical", 0); MD_EXPECT_LONG(md, "is_chemical_distfn", 0); MD_EXPECT_LONG(md, "is_chemical_srcsink", 0); MD_EXPECT_LONG(md, "is_aerosol", 0); MD_EXPECT_LONG(md, "is_aerosol_optical", 0); MD_EXPECT_LONG(md, "setCalendarId", 0); MD_EXPECT_LONG(md, "deleteCalendarId", 0); MD_EXPECT_LONG(md, "grib2LocalSectionPresent", 0); MD_EXPECT_LONG(md, "deleteLocalDefinition", 0); MD_EXPECT_LONG(md, "section2Length", 17); MD_EXPECT_LONG(md, "addEmptySection2", 0); MD_EXPECT_LONG(md, "grib2LocalSectionNumber", 1); MD_EXPECT_STRING(md, "marsClass", "od"); MD_EXPECT_STRING(md, "marsType", "an"); MD_EXPECT_STRING(md, "marsStream", "oper"); MD_EXPECT_STRING(md, "experimentVersionNumber", "0001"); MD_EXPECT_STRING(md, "class", "od"); MD_EXPECT_STRING(md, "type", "an"); MD_EXPECT_STRING(md, "stream", "oper"); MD_EXPECT_LONG(md, "productDefinitionTemplateNumberInternal", -1); MD_EXPECT_LONG(md, "localDefinitionNumber", 1); MD_EXPECT_LONG(md, "eps", 0); MD_EXPECT_LONG(md, "addExtraLocalSection", 0); MD_EXPECT_LONG(md, "deleteExtraLocalSection", 0); MD_EXPECT_LONG(md, "extraLocalSectionPresent", 0); MD_EXPECT_LONG(md, "gridDescriptionSectionPresent", 1); MD_EXPECT_LONG(md, "section3Length", 35); MD_EXPECT_LONG(md, "sourceOfGridDefinition", 0); MD_EXPECT_LONG(md, "numberOfDataPoints", 496); MD_EXPECT_LONG(md, "numberOfOctectsForNumberOfPoints", 0); MD_EXPECT_LONG(md, "interpretationOfNumberOfPoints", 0); MD_EXPECT_LONG(md, "PLPresent", 0); MD_EXPECT_LONG(md, "gridDefinitionTemplateNumber", 101); MD_EXPECT_STRING(md, "gridDefinitionDescription", "General unstructured grid"); MD_EXPECT_LONG(md, "shapeOfTheEarth", 6); MD_EXPECT_LONG(md, "numberOfGridUsed", 10); MD_EXPECT_LONG(md, "numberOfGridInReference", 1); MD_EXPECT_STRINGS(md, "unstructuredGridType", "unknown", "DART"); MD_EXPECT_STRING(md, "unstructuredGridSubtype", "T"); MD_EXPECT_STRING(md, "unstructuredGridUUID", "unknown"); MD_EXPECT_STRINGS(md, "gridName", "unknown", "DART_T"); MD_EXPECT_STRING(md, "gridType", "unstructured_grid"); MD_EXPECT_LONG(md, "section4Length", 34); MD_EXPECT_LONG(md, "NV", 0); MD_EXPECT_LONG(md, "neitherPresent", 0); MD_EXPECT_STRING(md, "datasetForLocal", "unknown"); MD_EXPECT_LONG(md, "productDefinitionTemplateNumber", 0); MD_EXPECT_LONG(md, "genVertHeightCoords", 0); MD_EXPECT_LONG(md, "parameterCategory", 0); MD_EXPECT_LONG(md, "parameterNumber", 0); MD_EXPECT_STRING(md, "parameterUnits", "Proportion"); MD_EXPECT_STRING(md, "parameterName", "Land cover (0 = sea, 1 = land)"); MD_EXPECT_LONG(md, "typeOfGeneratingProcess", 2); MD_EXPECT_LONG(md, "backgroundProcess", 0); MD_EXPECT_LONG(md, "generatingProcessIdentifier", 1); MD_EXPECT_LONG(md, "hoursAfterDataCutoff", 0); MD_EXPECT_LONG(md, "minutesAfterDataCutoff", 0); // MD_EXPECT_LONG(md, "indicatorOfUnitOfTimeRange", 1); MD_EXPECT_LONG(md, "stepUnits", 1); MD_EXPECT_LONG(md, "forecastTime", 0); MD_EXPECT_LONG(md, "startStep", 0); MD_EXPECT_LONG(md, "endStep", 0); MD_EXPECT_STRING(md, "stepRange", "0"); MD_EXPECT_LONG(md, "validityDate", 10101); MD_EXPECT_STRINGS(md, "validityTime", "0", "0000"); MD_EXPECT_STRING(md, "typeOfFirstFixedSurface", "168"); MD_EXPECT_STRING(md, "unitsOfFirstFixedSurface", "Numeric"); MD_EXPECT_STRING(md, "nameOfFirstFixedSurface", "Ocean model level"); MD_EXPECT_LONG(md, "scaleFactorOfFirstFixedSurface", 0); MD_EXPECT_LONG(md, "scaledValueOfFirstFixedSurface", 2147483647); MD_EXPECT_LONG(md, "typeOfSecondFixedSurface", 255); MD_EXPECT_STRING(md, "unitsOfSecondFixedSurface", "unknown"); MD_EXPECT_STRING(md, "nameOfSecondFixedSurface", "Missing"); MD_EXPECT_LONG(md, "scaleFactorOfSecondFixedSurface", 0); MD_EXPECT_LONG(md, "scaledValueOfSecondFixedSurface", 2147483647); MD_EXPECT_STRING(md, "pressureUnits", "hPa"); MD_EXPECT_STRING(md, "typeOfLevel", "oceanModel"); MD_EXPECT_LONG(md, "level", 0); MD_EXPECT_LONG(md, "bottomLevel", 0); MD_EXPECT_LONG(md, "topLevel", 0); MD_EXPECT_STRING(md, "tempPressureUnits", "hPa"); MD_EXPECT_STRING(md, "levtype", "o3d"); MD_EXPECT_LONG(md, "PVPresent", 0); MD_EXPECT_STRING(md, "deletePV", "1"); MD_EXPECT_LONG(md, "lengthOfHeaders", 107); MD_EXPECT_LONG(md, "section5Length", 21); MD_EXPECT_LONG(md, "numberOfValues", 496); MD_EXPECT_LONG(md, "dataRepresentationTemplateNumber", 0); MD_EXPECT_STRING(md, "packingType", "grid_simple"); MD_EXPECT_LONG(md, "referenceValue", 0); MD_EXPECT_DOUBLE(md, "referenceValueError", 1.17549e-38); MD_EXPECT_LONG(md, "binaryScaleFactor", -15); MD_EXPECT_LONG(md, "decimalScaleFactor", 0); MD_EXPECT_LONG(md, "optimizeScaleFactor", 0); MD_EXPECT_LONG(md, "bitsPerValue", 0); MD_EXPECT_LONG(md, "typeOfOriginalFieldValues", 0); MD_EXPECT_LONG(md, "section6Length", 6); MD_EXPECT_LONG(md, "bitMapIndicator", 255); MD_EXPECT_LONG(md, "bitmapPresent", 0); MD_EXPECT_LONG(md, "section7Length", 5); MD_EXPECT_DOUBLE(md, "packingError", 1.17549e-38); MD_EXPECT_DOUBLE(md, "unpackedError", 1.17549e-38); MD_EXPECT_LONG(md, "maximum", 0); MD_EXPECT_LONG(md, "minimum", 0); MD_EXPECT_LONG(md, "average", 0); MD_EXPECT_LONG(md, "numberOfMissing", 0); MD_EXPECT_LONG(md, "standardDeviation", 0); MD_EXPECT_LONG(md, "skewness", 0); MD_EXPECT_LONG(md, "kurtosis", 0); MD_EXPECT_LONG(md, "isConstant", 1); MD_EXPECT_LONG(md, "changeDecimalPrecision", 0); MD_EXPECT_LONG(md, "decimalPrecision", 0); MD_EXPECT_LONG(md, "setBitsPerValue", 0); MD_EXPECT_LONG(md, "getNumberOfValues", 496); MD_EXPECT_LONG(md, "scaleValuesBy", 1); MD_EXPECT_LONG(md, "offsetValuesBy", 0); MD_EXPECT_STRING(md, "productType", "unknown"); MD_EXPECT_LONG(md, "section8Length", 4); MD_EXPECT_STRING(md, "7777", "7777"); MD_EXPECT_STRING(md, "uuidOfHGrid", "66a341d21dcf11b2880c0f1645f3d1dc"); } } //---------------------------------------------------------------------------------------------------------------------- CASE("test codessplitter unstr_latlot.tmpl String") { eckit::MemoryHandle data(static_cast(unstr_latlon), sizeof(unstr_latlon)); std::cout << "Data location " << ((size_t)&unstr_latlon) << std::endl; eckit::message::Reader reader(data); eckit::message::Message msg; msg = reader.next(); EXPECT(msg); MetadataSetter md; eckit::message::TypedSetter gatherer{md}; eckit::message::GetMetadataOptions mdOpts{}; mdOpts.valueRepresentation = eckit::message::ValueRepresentation::String; mdOpts.nameSpace = ""; msg.getMetadata(gatherer, mdOpts); { MD_EXPECT_STRING(md, "globalDomain", "g"); MD_EXPECT_STRING(md, "GRIBEditionNumber", "2"); // This is not easy to test, as the latest official version can increment... // MD_EXPECT_STRING(md, "tablesVersionLatestOfficial", "30"); // MD_EXPECT_STRING(md, "tablesVersionLatest", "30"); MD_EXPECT_STRING(md, "grib2divider", "1e+06"); MD_EXPECT_STRING(md, "angleSubdivisions", "1e+06"); MD_EXPECT_STRING(md, "missingValue", "9999"); MD_EXPECT_STRING(md, "ieeeFloats", "1"); MD_EXPECT_STRING(md, "isHindcast", "0"); MD_EXPECT_STRING(md, "section0Length", "16"); MD_EXPECT_STRING(md, "identifier", "GRIB"); MD_EXPECT_STRING(md, "discipline", "2"); MD_EXPECT_STRING(md, "editionNumber", "2"); MD_EXPECT_STRING(md, "totalLength", "159"); MD_EXPECT_STRING(md, "section1Length", "21"); MD_EXPECT_STRING(md, "centre", "ecmf"); MD_EXPECT_STRING(md, "centreDescription", "European Centre for Medium-Range Weather Forecasts"); MD_EXPECT_STRING(md, "subCentre", "255"); MD_EXPECT_STRING(md, "tablesVersion", "25"); MD_EXPECT_STRING(md, "masterDir", "grib2/tables/[tablesVersion]"); MD_EXPECT_STRING(md, "localTablesVersion", "0"); MD_EXPECT_STRING(md, "significanceOfReferenceTime", "0"); MD_EXPECT_STRING(md, "year", "1"); MD_EXPECT_STRING(md, "month", "1"); MD_EXPECT_STRING(md, "day", "1"); MD_EXPECT_STRING(md, "hour", "0"); MD_EXPECT_STRING(md, "minute", "0"); MD_EXPECT_STRING(md, "second", "0"); MD_EXPECT_STRING(md, "dataDate", "10101"); MD_EXPECT_STRING(md, "julianDay", "1.72142e+06"); MD_EXPECT_STRING(md, "dataTime", "0000"); MD_EXPECT_STRING(md, "productionStatusOfProcessedData", "0"); MD_EXPECT_STRING(md, "typeOfProcessedData", "an"); MD_EXPECT_STRING(md, "selectStepTemplateInterval", "1"); MD_EXPECT_STRING(md, "selectStepTemplateInstant", "1"); MD_EXPECT_STRING(md, "stepType", "instant"); MD_EXPECT_STRING(md, "is_chemical", "0"); MD_EXPECT_STRING(md, "is_chemical_distfn", "0"); MD_EXPECT_STRING(md, "is_chemical_srcsink", "0"); MD_EXPECT_STRING(md, "is_aerosol", "0"); MD_EXPECT_STRING(md, "is_aerosol_optical", "0"); MD_EXPECT_STRING(md, "setCalendarId", "0"); MD_EXPECT_STRING(md, "deleteCalendarId", "0"); MD_EXPECT_STRING(md, "grib2LocalSectionPresent", "0"); MD_EXPECT_STRING(md, "deleteLocalDefinition", "0"); MD_EXPECT_STRING(md, "section2Length", "17"); MD_EXPECT_STRING(md, "addEmptySection2", "0"); MD_EXPECT_STRING(md, "grib2LocalSectionNumber", "1"); MD_EXPECT_STRING(md, "marsClass", "od"); MD_EXPECT_STRING(md, "marsType", "an"); MD_EXPECT_STRING(md, "marsStream", "oper"); MD_EXPECT_STRING(md, "experimentVersionNumber", "0001"); MD_EXPECT_STRING(md, "class", "od"); MD_EXPECT_STRING(md, "type", "an"); MD_EXPECT_STRING(md, "stream", "oper"); MD_EXPECT_STRING(md, "productDefinitionTemplateNumberInternal", "-1"); MD_EXPECT_STRING(md, "localDefinitionNumber", "1"); MD_EXPECT_STRING(md, "eps", "0"); MD_EXPECT_STRING(md, "addExtraLocalSection", "0"); MD_EXPECT_STRING(md, "deleteExtraLocalSection", "0"); MD_EXPECT_STRING(md, "extraLocalSectionPresent", "0"); MD_EXPECT_STRING(md, "gridDescriptionSectionPresent", "1"); MD_EXPECT_STRING(md, "section3Length", "35"); MD_EXPECT_STRING(md, "sourceOfGridDefinition", "0"); MD_EXPECT_STRING(md, "numberOfDataPoints", "496"); MD_EXPECT_STRING(md, "numberOfOctectsForNumberOfPoints", "0"); MD_EXPECT_STRING(md, "interpretationOfNumberOfPoints", "0"); MD_EXPECT_STRING(md, "PLPresent", "0"); MD_EXPECT_STRING(md, "gridDefinitionTemplateNumber", "101"); MD_EXPECT_STRING(md, "gridDefinitionDescription", "General unstructured grid"); MD_EXPECT_STRING(md, "shapeOfTheEarth", "6"); MD_EXPECT_STRING(md, "numberOfGridUsed", "10"); MD_EXPECT_STRING(md, "numberOfGridInReference", "1"); MD_EXPECT_STRING(md, "uuidOfHGrid", "66a341d21dcf11b2880c0f1645f3d1dc"); MD_EXPECT_STRINGS(md, "unstructuredGridType", "unknown", "DART"); MD_EXPECT_STRING(md, "unstructuredGridSubtype", "T"); MD_EXPECT_STRING(md, "unstructuredGridUUID", "unknown"); MD_EXPECT_STRINGS(md, "gridName", "unknown", "DART_T"); MD_EXPECT_STRING(md, "gridType", "unstructured_grid"); MD_EXPECT_STRING(md, "section4Length", "34"); MD_EXPECT_STRING(md, "NV", "0"); MD_EXPECT_STRING(md, "neitherPresent", "0"); MD_EXPECT_STRING(md, "datasetForLocal", "unknown"); MD_EXPECT_STRING(md, "productDefinitionTemplateNumber", "0"); MD_EXPECT_STRING(md, "genVertHeightCoords", "0"); MD_EXPECT_STRING(md, "parameterCategory", "0"); MD_EXPECT_STRING(md, "parameterNumber", "0"); MD_EXPECT_STRING(md, "parameterUnits", "Proportion"); MD_EXPECT_STRING(md, "parameterName", "Land cover (0 = sea, 1 = land)"); MD_EXPECT_STRING(md, "typeOfGeneratingProcess", "2"); MD_EXPECT_STRING(md, "backgroundProcess", "0"); MD_EXPECT_STRING(md, "generatingProcessIdentifier", "1"); MD_EXPECT_STRING(md, "hoursAfterDataCutoff", "0"); MD_EXPECT_STRING(md, "minutesAfterDataCutoff", "0"); // MD_EXPECT_STRING(md, "indicatorOfUnitOfTimeRange", "h"); MD_EXPECT_STRING(md, "stepUnits", "h"); MD_EXPECT_STRING(md, "forecastTime", "0"); MD_EXPECT_STRING(md, "startStep", "0"); MD_EXPECT_STRING(md, "endStep", "0"); MD_EXPECT_STRING(md, "stepRange", "0"); MD_EXPECT_STRING(md, "validityDate", "10101"); MD_EXPECT_STRINGS(md, "validityTime", "0", "0000"); MD_EXPECT_STRING(md, "typeOfFirstFixedSurface", "168"); MD_EXPECT_STRING(md, "unitsOfFirstFixedSurface", "Numeric"); MD_EXPECT_STRING(md, "nameOfFirstFixedSurface", "Ocean model level"); MD_EXPECT_STRING(md, "scaleFactorOfFirstFixedSurface", "0"); MD_EXPECT_STRING(md, "scaledValueOfFirstFixedSurface", "MISSING"); MD_EXPECT_STRING(md, "typeOfSecondFixedSurface", "255"); MD_EXPECT_STRING(md, "unitsOfSecondFixedSurface", "unknown"); MD_EXPECT_STRING(md, "nameOfSecondFixedSurface", "Missing"); MD_EXPECT_STRING(md, "scaleFactorOfSecondFixedSurface", "0"); MD_EXPECT_STRING(md, "scaledValueOfSecondFixedSurface", "MISSING"); MD_EXPECT_STRING(md, "pressureUnits", "hPa"); MD_EXPECT_STRING(md, "typeOfLevel", "oceanModel"); MD_EXPECT_STRING(md, "level", "0"); MD_EXPECT_STRING(md, "bottomLevel", "0"); MD_EXPECT_STRING(md, "topLevel", "0"); MD_EXPECT_STRING(md, "tempPressureUnits", "hPa"); MD_EXPECT_STRING(md, "levtype", "o3d"); MD_EXPECT_STRING(md, "PVPresent", "0"); MD_EXPECT_STRING(md, "deletePV", "1"); MD_EXPECT_STRING(md, "lengthOfHeaders", "107"); MD_EXPECT_STRING(md, "section5Length", "21"); MD_EXPECT_STRING(md, "numberOfValues", "496"); MD_EXPECT_STRING(md, "dataRepresentationTemplateNumber", "0"); MD_EXPECT_STRING(md, "packingType", "grid_simple"); MD_EXPECT_STRING(md, "referenceValue", "0"); MD_EXPECT_STRING(md, "referenceValueError", "1.17549e-38"); MD_EXPECT_STRING(md, "binaryScaleFactor", "-15"); MD_EXPECT_STRING(md, "decimalScaleFactor", "0"); MD_EXPECT_STRING(md, "optimizeScaleFactor", "0"); MD_EXPECT_STRING(md, "bitsPerValue", "0"); MD_EXPECT_STRING(md, "typeOfOriginalFieldValues", "0"); MD_EXPECT_STRING(md, "section6Length", "6"); MD_EXPECT_STRING(md, "bitMapIndicator", "255"); MD_EXPECT_STRING(md, "bitmapPresent", "0"); MD_EXPECT_STRING(md, "section7Length", "5"); MD_EXPECT_STRING(md, "packingError", "1.17549e-38"); MD_EXPECT_STRING(md, "unpackedError", "1.17549e-38"); MD_EXPECT_STRING(md, "maximum", "0"); MD_EXPECT_STRING(md, "minimum", "0"); MD_EXPECT_STRING(md, "average", "0"); MD_EXPECT_STRING(md, "numberOfMissing", "0"); MD_EXPECT_STRING(md, "standardDeviation", "0"); MD_EXPECT_STRING(md, "skewness", "0"); MD_EXPECT_STRING(md, "kurtosis", "0"); MD_EXPECT_STRING(md, "isConstant", "1"); MD_EXPECT_STRING(md, "changeDecimalPrecision", "0"); MD_EXPECT_STRING(md, "decimalPrecision", "0"); MD_EXPECT_STRING(md, "setBitsPerValue", "0"); MD_EXPECT_STRING(md, "getNumberOfValues", "496"); MD_EXPECT_STRING(md, "scaleValuesBy", "1"); MD_EXPECT_STRING(md, "offsetValuesBy", "0"); MD_EXPECT_STRING(md, "productType", "unknown"); MD_EXPECT_STRING(md, "section8Length", "4"); MD_EXPECT_STRING(md, "7777", "7777"); } } //---------------------------------------------------------------------------------------------------------------------- } // namespace metkit::codes::test int main(int argc, char** argv) { return eckit::testing::run_tests(argc, argv); } metkit-1.16.0/tests/test_context.cc000066400000000000000000000027231513171467200173030ustar00rootroot00000000000000/* * (C) Copyright 2025- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ /// @file test_step.cc /// @author Emanuele Danovaro /// @date March 2025 #include #include #include #include "eckit/testing/Test.h" #include "metkit/mars/MarsLanguage.h" #include "metkit/mars/Type.h" namespace metkit::mars::test { using ::eckit::BadValue; //----------------------------------------------------------------------------- CASE("Context match") { Context c; std::set cc{"s2", "ti"}; c.add(std::make_unique("class", cc)); std::set tt{"cf"}; c.add(std::make_unique("type", tt)); std::string text = "retrieve, " "class=ti,date=20250414,time=12,origin=all,expver=all,type=cf,stream=enfo,levtype=sfc,param=2t,step=24,expect=" "any,target=data.reference"; metkit::mars::MarsRequest r = MarsRequest::parse(text, true); EXPECT(c.matches(r)); } //----------------------------------------------------------------------------- } // namespace metkit::mars::test int main(int argc, char** argv) { return eckit::testing::run_tests(argc, argv); } metkit-1.16.0/tests/test_date.cc000066400000000000000000000067051513171467200165400ustar00rootroot00000000000000/* * (C) Copyright 1996- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ /// @file test_date.cc /// @author Emanuele Danovaro /// @date March 2025 #include #include #include "eckit/testing/Test.h" #include "eckit/types/Date.h" #include "eckit/value/Value.h" #include "metkit/mars/MarsLanguage.h" #include "metkit/mars/TypeDate.h" namespace metkit::mars::test { using ::eckit::BadValue; using ::eckit::Value; //----------------------------------------------------------------------------- void assertTypeExpansion(const std::string& name, std::vector values, const std::vector& expected) { static MarsLanguage language("retrieve"); language.type(name)->expand(values); EXPECT_EQUAL(expected, values); } std::string date(long d) { if (d <= 0) { eckit::Date day(d); d = day.yyyymmdd(); } return std::to_string(d); } CASE("Test TypeDate expansions") { TypeDate tdate("date", Value()); Type& td(tdate); assertTypeExpansion("date", {"20140506"}, {"20140506"}); assertTypeExpansion("date", {"2014-05-06"}, {"20140506"}); assertTypeExpansion("date", {"20140506", "20140507"}, {"20140506", "20140507"}); assertTypeExpansion("date", {"20140506", "to", "20140506"}, {"20140506"}); assertTypeExpansion("date", {"20140506", "to", "20140507"}, {"20140506", "20140507"}); assertTypeExpansion("date", {"20140506", "to", "20140508"}, {"20140506", "20140507", "20140508"}); assertTypeExpansion("date", {"20140504", "20140506", "to", "20140508"}, {"20140504", "20140506", "20140507", "20140508"}); assertTypeExpansion("date", {"-1", "0"}, {date(-1), date(0)}); assertTypeExpansion("date", {"-1", "to", "-3"}, {date(-1), date(-2), date(-3)}); assertTypeExpansion("date", {"-3", "to", "-1"}, {date(-3), date(-2), date(-1)}); assertTypeExpansion("date", {"-5", "to", "-1", "by", "2"}, {date(-5), date(-3), date(-1)}); assertTypeExpansion("date", {"2"}, {"feb"}); assertTypeExpansion("date", {"jan"}, {"jan"}); assertTypeExpansion("date", {"september"}, {"sep"}); assertTypeExpansion("date", {"9"}, {"sep"}); assertTypeExpansion("date", {"1-01"}, {"jan-1"}); assertTypeExpansion("date", {"jan-01"}, {"jan-1"}); assertTypeExpansion("date", {"january-01"}, {"jan-1"}); assertTypeExpansion("date", {"feb-23"}, {"feb-23"}); assertTypeExpansion("date", {"2018-23"}, {"20180123"}); assertTypeExpansion("date", {"2018-41"}, {"20180210"}); { EXPECT_THROWS(auto vv = td.tidy("20141506")); // throws BadDate that is not exported } { EXPECT_THROWS(auto vv = td.tidy("20180132")); // throws BadDate that is not exported } { EXPECT_THROWS(auto vv = td.tidy("202401366")); // throws BadDate that is not exported } { EXPECT_THROWS_AS(auto vv = td.tidy("abc"), BadValue); } { EXPECT_THROWS_AS(auto vv = td.tidy("abc-01"), BadValue); } } //----------------------------------------------------------------------------- } // namespace metkit::mars::test int main(int argc, char** argv) { return eckit::testing::run_tests(argc, argv); } metkit-1.16.0/tests/test_expand.cc000066400000000000000000001675121513171467200171060ustar00rootroot00000000000000/* * (C) Copyright 1996- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation * nor does it submit to any jurisdiction. */ /// @file test_expand.cc /// @date Jan 2016 /// @author Florian Rathgeber /// @author Emanuele Danovaro #include #include #include #include "eckit/filesystem/LocalPathName.h" #include "eckit/filesystem/StdDir.h" #include "eckit/types/Date.h" #include "eckit/utils/StringTools.h" #include "metkit/mars/MarsExpansion.h" #include "metkit/mars/MarsLanguage.h" #include "metkit/mars/MarsParser.h" #include "metkit/mars/MarsRequest.h" #include "metkit/mars/Type.h" #include "eckit/testing/Test.h" #include "eckit/utils/Tokenizer.h" using namespace eckit::testing; namespace metkit::mars::test { namespace { using ExpectedVals = std::map>; /** * @brief We can specify a set of keys which should be ignored when not specified in the user request. * In case the user requests defines them, check them regardless. This is mean to ignore auto-injected * keys e.g. for resol. */ std::set ignore_{"repres", "resol"}; std::string date(long d) { if (d <= 0) { eckit::Date day(d); d = day.yyyymmdd(); } return std::to_string(d); } std::string date(std::string d) { if (d == "0" || d[0] == '-') { long dd = std::stol(d); eckit::Date day(dd); return std::to_string(day.yyyymmdd()); } return d; } struct ExpectedRequest { ExpectedRequest() = default; ExpectedRequest(std::string vrb, ExpectedVals vv, std::vector dd) : verb(vrb), vals(vv), dates(dd) {} ExpectedRequest(std::string vrb, ExpectedVals vv, std::vector dd) : verb(vrb), vals(vv) { dates.reserve(dd.size()); for (long d : dd) { dates.push_back(date(d)); } } std::string verb; ExpectedVals vals; std::vector dates; }; } // namespace //----------------------------------------------------------------------------- void expand(const MarsRequest& r, const ExpectedRequest& expected, std::set ignore) { try { EXPECT_EQUAL(expected.verb, r.verb()); for (const auto& e : expected.vals) { if (!r.has(e.first)) { if (ignore.find(e.first) != ignore.end()) { continue; } std::cerr << eckit::Colour::red << "Missing keyword: " << e.first << eckit::Colour::reset << std::endl; } EXPECT(r.has(e.first)); auto vv = r.values(e.first); if (e.first != "date") { // dates are verified at a later stage EXPECT_EQUAL(e.second.size(), vv.size()); } for (int i = 0; i < vv.size(); i++) { if (e.first == "grid") { EXPECT_EQUAL(eckit::StringTools::upper(e.second.at(i)), vv.at(i)); } else { if (e.first == "resol") { EXPECT_EQUAL(e.second.at(i), eckit::StringTools::lower(vv.at(i))); } else { EXPECT_EQUAL(e.second.at(i), vv.at(i)); } } } } if (expected.dates.size() > 0) { EXPECT(r.has("date")); auto dd = r.values("date"); EXPECT_EQUAL(expected.dates.size(), dd.size()); for (int i = 0; i < expected.dates.size(); i++) { EXPECT_EQUAL(date(expected.dates.at(i)), dd.at(i)); } } } catch (...) { std::cerr << "Error comparing " << r << " with " << expected.vals << " dates " << expected.dates << std::endl; throw; } } void expand(const MarsRequest& r, const std::string& verb, const ExpectedVals& expected, std::vector& dates, std::set ignore) { expand(r, {verb, expected, dates}, ignore); } void expand(const std::string& text, const std::string& verb, const ExpectedVals& expected, std::vector dates, bool strict = false) { MarsRequest r = MarsRequest::parse(text, strict); std::set ignore; std::string tt = eckit::StringTools::lower(text); for (const auto& i : ignore_) { auto idx = tt.find(i); if (idx == std::string::npos) { ignore.insert(i); } } expand(r, {verb, expected, dates}, ignore); } void parse(const std::string& req, ExpectedRequest& expected) { eckit::Tokenizer c(","); eckit::Tokenizer e("="); eckit::Tokenizer s("/"); eckit::StringList tokens; c(req, tokens); for (const auto& t : tokens) { auto tt = eckit::StringTools::trim(t); if (expected.verb.empty()) { expected.verb = eckit::StringTools::lower(tt); continue; } eckit::StringList kv; e(tt, kv); EXPECT_EQUAL(2, kv.size()); auto key = eckit::StringTools::lower(eckit::StringTools::trim(kv[0])); if (key == "date") { EXPECT_EQUAL(0, expected.dates.size()); } eckit::StringList vals; s(kv[1], vals); std::vector vv; for (auto v : vals) { auto val = eckit::StringTools::trim(v); if (key != "source" && key != "target" && key != "intgrid" && key != "grid") { val = eckit::StringTools::lower(val); } if (key == "date") { expected.dates.push_back(date(val)); } else { vv.push_back(val); } } if (key != "date") { expected.vals.emplace(key, vv); } } } void expand(const std::string& text, const std::string& expected, bool strict = false, std::vector dates = {}) { ExpectedRequest out; out.dates.reserve(dates.size()); for (long d : dates) { out.dates.push_back(date(d)); } parse(expected, out); MarsRequest r = MarsRequest::parse(text, strict); std::set ignore; std::string tt = eckit::StringTools::lower(text); for (const auto& i : ignore_) { auto idx = tt.find(i); if (idx == std::string::npos) { ignore.insert(i); } } expand(r, out, ignore); } void expand(const std::string& text, const std::vector& expected, bool strict = false, std::vector> dates = {}) { ExpectedVals out; std::istringstream in(text); std::vector reqs = MarsRequest::parse(in, strict); std::set ignore; std::string tt = eckit::StringTools::lower(text); for (const auto& i : ignore_) { auto idx = tt.find(i); if (idx == std::string::npos) { ignore.insert(i); } } ASSERT(dates.size() == 0 || dates.size() == expected.size()); EXPECT_EQUAL(expected.size(), reqs.size()); for (size_t i = 0; i < expected.size(); i++) { ExpectedRequest expectedReq; if (dates.size() != 0) { expectedReq.dates.reserve(dates.at(i).size()); for (long d : dates.at(i)) { expectedReq.dates.push_back(date(d)); } } parse(expected.at(i), expectedReq); expand(reqs.at(i), expectedReq, ignore); } } CASE("test_metkit_expand_1") { const char* text = "ret,date=-5/to/-1"; ExpectedVals expected{{"class", {"od"}}, {"domain", {"g"}}, {"expver", {"0001"}}, {"levelist", {"1000", "850", "700", "500", "400", "300"}}, {"levtype", {"pl"}}, {"param", {"129"}}, {"step", {"0"}}, {"stream", {"oper"}}, {"time", {"1200"}}, {"type", {"an"}}}; expand(text, "retrieve", expected, {-5, -4, -3, -2, -1}); const char* text2 = "ret,date=-5/to/-1."; expand(text2, "retrieve", expected, {-5, -4, -3, -2, -1}); const char* expectedStr = "RETRIEVE,CLASS=OD,TYPE=AN,STREAM=OPER,EXPVER=0001,REPRES=SH,LEVTYPE=PL,LEVELIST=1000/850/700/500/400/" "300,PARAM=129,TIME=1200,STEP=0,DOMAIN=G"; expand(text, expectedStr, false, {-5, -4, -3, -2, -1}); } CASE("test_metkit_expand_2") { { const char* text = "ret,date=-1"; ExpectedVals expected{{"class", {"od"}}, {"domain", {"g"}}, {"expver", {"0001"}}, {"levelist", {"1000", "850", "700", "500", "400", "300"}}, {"levtype", {"pl"}}, {"param", {"129"}}, {"step", {"0"}}, {"stream", {"oper"}}, {"time", {"1200"}}, {"type", {"an"}}}; expand(text, "retrieve", expected, {-1}); } { const char* text = "ret,levtype=ml"; ExpectedVals expected{{"class", {"od"}}, {"domain", {"g"}}, {"expver", {"0001"}}, {"levelist", {"1000", "850", "700", "500", "400", "300"}}, // {"levelist", {"1","2"}}, // keeping the old default, for MARS client tests {"levtype", {"ml"}}, {"param", {"129"}}, {"step", {"0"}}, {"stream", {"oper"}}, {"time", {"1200"}}, {"type", {"an"}}}; expand(text, "retrieve", expected, {-1}); } } CASE("test_metkit_expand_3") { const char* text = "ret,date=-5/to/-1,grid=n640"; ExpectedVals expected{{"class", {"od"}}, {"domain", {"g"}}, {"expver", {"0001"}}, {"levelist", {"1000", "850", "700", "500", "400", "300"}}, {"levtype", {"pl"}}, {"param", {"129"}}, {"step", {"0"}}, {"stream", {"oper"}}, {"time", {"1200"}}, {"type", {"an"}}, {"grid", {"N640"}}}; expand(text, "retrieve", expected, {-5, -4, -3, -2, -1}); } CASE("test_metkit_expand_4") { const char* text = "ret,date=-5/to/-1,grid=o640"; ExpectedVals expected{{"class", {"od"}}, {"domain", {"g"}}, {"expver", {"0001"}}, {"levelist", {"1000", "850", "700", "500", "400", "300"}}, {"levtype", {"pl"}}, {"param", {"129"}}, {"step", {"0"}}, {"stream", {"oper"}}, {"time", {"1200"}}, {"type", {"an"}}, {"grid", {"O640"}}}; expand(text, "retrieve", expected, {-5, -4, -3, -2, -1}); } CASE("test_metkit_expand_5") { const char* text = "retrieve,class=od,date=20050601,diagnostic=1,expver=1,iteration=0,levelist=1,levtype=ml,param=155.129,stream=" "sens,time=1200,type=sg"; ExpectedVals expected{{"class", {"od"}}, {"diagnostic", {"1"}}, {"domain", {"g"}}, {"expver", {"0001"}}, {"iteration", {"0"}}, {"levelist", {"1"}}, {"levtype", {"ml"}}, {"param", {"129155"}}, {"step", {"0"}}, {"stream", {"sens"}}, {"time", {"1200"}}, {"type", {"sg"}}}; expand(text, "retrieve", expected, {20050601}); } CASE("test_metkit_expand_6") { const char* text = "retrieve,class=rd,expver=hl1m,stream=oper,date=20000801,time=0000,domain=g,type=fc,levtype=pl,step=24,param=" "129,levelist=1/to/31"; ExpectedVals expected{{"class", {"rd"}}, {"expver", {"hl1m"}}, {"stream", {"oper"}}, {"time", {"0000"}}, {"domain", {"g"}}, {"type", {"fc"}}, {"levtype", {"pl"}}, {"step", {"24"}}, {"param", {"129"}}}; std::vector levelist; for (int i = 1; i <= 31; i++) { levelist.push_back(std::to_string(i)); } expected["levelist"] = levelist; expand(text, "retrieve", expected, {20000801}); } CASE("test_metkit_expand_7") { const char* text = "retrieve,class=rd,expver=hl1m,stream=oper,date=20000801,time=0000,domain=g,type=fc,levtype=pl,step=24,param=" "129,levelist=0.01/0.7"; ExpectedVals expected{{"class", {"rd"}}, {"expver", {"hl1m"}}, {"stream", {"oper"}}, {"time", {"0000"}}, {"domain", {"g"}}, {"type", {"fc"}}, {"levtype", {"pl"}}, {"step", {"24"}}, {"param", {"129"}}, {"levelist", {".01", ".7"}}}; expand(text, "retrieve", expected, {20000801}); } CASE("test_metkit_expand_8") { const char* text = "retrieve,class=rd,expver=hl1m,stream=oper,date=20000801,time=0000,domain=g,type=fc,levtype=pl,step=24,param=" "129,levelist=0.1/to/0.7/by/0.2"; ExpectedVals expected{{"class", {"rd"}}, {"expver", {"hl1m"}}, {"stream", {"oper"}}, {"time", {"0000"}}, {"domain", {"g"}}, {"type", {"fc"}}, {"levtype", {"pl"}}, {"step", {"24"}}, {"param", {"129"}}, {"levelist", {".1", ".3", ".5", ".7"}}}; expand(text, "retrieve", expected, {20000801}); } CASE("test_metkit_expand_9_strict") { const char* text = "retrieve,class=rd,expver=hm1u,stream=weeh,time=0000,date=20210101,domain=g,hdate=20190101"; { std::istringstream in(text); MarsParser parser(in); MarsExpansion expand(false, false); std::vector v = expand.expand(parser.parse()); EXPECT_EQUAL(v.size(), 1); } { std::istringstream in(text); MarsParser parser(in); MarsExpansion expand(false, true); std::vector v = expand.expand(parser.parse()); EXPECT_EQUAL(v.size(), 1); } { const char* text = "retrieve,class=od,expver=1,date=20240304,time=0,type=fc,levtype=sfc,levelist=1/2/" "3,step=0,param=2t,target=out"; EXPECT_THROWS_AS(MarsRequest::parse(text, true), eckit::UserError); const char* expected = "RETRIEVE,CLASS=OD,TYPE=FC,STREAM=OPER,EXPVER=0001,REPRES=GG,LEVTYPE=SFC,PARAM=167,DATE=20240304,TIME=0000," "STEP=0,DOMAIN=G,TARGET=out"; expand(text, expected, false); } { const char* text = "retrieve,class=od,expver=1,stream=enfo,date=20240304,time=0,type=cf,levtype=sfc,levelist=1/2/" "3,step=0,param=2t,number=1/2/3,target=out"; EXPECT_THROWS_AS(MarsRequest::parse(text, true), eckit::UserError); const char* expected = "RETRIEVE,CLASS=OD,TYPE=CF,STREAM=ENFO,EXPVER=0001,REPRES=SH,LEVTYPE=SFC,PARAM=167,DATE=20240304,TIME=0000," "STEP=0,DOMAIN=G,TARGET=out"; expand(text, expected, false); } } CASE("test_metkit_expand_10_strict") { const char* text = "retrieve,class=rd,expver=hm1u,stream=wees,time=0000,date=20210101,domain=g,hdate=20190101"; { std::istringstream in(text); MarsParser parser(in); MarsExpansion expand(false, false); std::vector v = expand.expand(parser.parse()); EXPECT_EQUAL(v.size(), 1); } } CASE("test_metkit_expand_multirequest-1") { const std::string text = "ret,date=-5/to/-2.\nret,date=-1"; std::istringstream in(text); std::vector reqs = MarsRequest::parse(in, false); EXPECT_EQUAL(reqs.size(), 2); ExpectedVals expected{{"class", {"od"}}, {"domain", {"g"}}, {"expver", {"0001"}}, {"levelist", {"1000", "850", "700", "500", "400", "300"}}, {"levtype", {"pl"}}, {"param", {"129"}}, {"step", {"0"}}, {"stream", {"oper"}}, {"time", {"1200"}}, {"type", {"an"}}}; expand(reqs.at(0), {"retrieve", expected, std::vector{-5, -4, -3, -2}}, ignore_); expand(reqs.at(1), {"retrieve", expected, std::vector{-1}}, ignore_); } CASE("test_metkit_expand_multirequest-2") { const std::string text = "ret,date=-5/to/-2.\nret,date=-1"; std::string expectedStr = "retrieve,class=od,domain=g,expver=0001,levelist=1000/850/700/500/400/" "300,levtype=pl,param=129,step=0,stream=oper,time=1200,type=an"; expand(text, {expectedStr, expectedStr}, false, {{-5, -4, -3, -2}, {-1}}); } CASE("test_metkit_expand_multirequest-3") { const char* text = "retrieve,accuracy=16,area=14.8/-19.6/-14.5/19.8,class=od,date=20230810,expver=1,grid=0.09/0.09,levelist=1/" "to/137,levtype=ml,number=-1,param=z,process=local,rotation=-78.8/-61.0,step=000,stream=scda,time=18," "type=an,target=\"reference.ect1qF.data\"\n" "ret,rotation=off,target=\"out\""; const char* expected1 = "RETRIEVE,CLASS=OD,TYPE=AN,STREAM=SCDA,EXPVER=0001,REPRES=SH,LEVTYPE=ML,LEVELIST=1/2/3/4/5/6/7/8/9/10/11/" "12/13/14/15/16/17/18/19/20/21/22/23/24/25/26/27/28/29/30/31/32/33/34/35/36/37/38/39/40/41/42/43/44/45/46/" "47/48/49/50/51/52/53/54/55/56/57/58/59/60/61/62/63/64/65/66/67/68/69/70/71/72/73/74/75/76/77/78/79/80/81/" "82/83/84/85/86/87/88/89/90/91/92/93/94/95/96/97/98/99/100/101/102/103/104/105/106/107/108/109/110/111/112/" "113/114/115/116/117/118/119/120/121/122/123/124/125/126/127/128/129/130/131/132/133/134/135/136/137," "PARAM=129,DATE=20230810,TIME=1800,STEP=0,DOMAIN=G,TARGET=reference.ect1qF.data,RESOL=AUTO,ACCURACY=16," "AREA=14.8/-19.6/-14.5/19.8,ROTATION=-78.8/-61,GRID=.09/.09,PROCESS=LOCAL"; const char* expected2 = "RETRIEVE,CLASS=OD,TYPE=AN,STREAM=SCDA,EXPVER=0001,REPRES=SH,LEVTYPE=ML,LEVELIST=1/2/3/4/5/6/7/8/9/10/11/" "12/13/14/15/16/17/18/19/20/21/22/23/24/25/26/27/28/29/30/31/32/33/34/35/36/37/38/39/40/41/42/43/44/45/46/" "47/48/49/50/51/52/53/54/55/56/57/58/59/60/61/62/63/64/65/66/67/68/69/70/71/72/73/74/75/76/77/78/79/80/81/" "82/83/84/85/86/87/88/89/90/91/92/93/94/95/96/97/98/99/100/101/102/103/104/105/106/107/108/109/110/111/112/" "113/114/115/116/117/118/119/120/121/122/123/124/125/126/127/128/129/130/131/132/133/134/135/136/137," "PARAM=129,DATE=20230810,TIME=1800,STEP=0,DOMAIN=G,TARGET=out,RESOL=AUTO,ACCURACY=16," "AREA=14.8/-19.6/-14.5/19.8,GRID=.09/.09,PROCESS=LOCAL"; expand(text, std::vector{expected1, expected2}); } void expandKeyThrows(const std::string& key, std::vector values) { static metkit::mars::MarsLanguage language("retrieve"); metkit::mars::Type* t = language.type(key); EXPECT_THROWS_AS(t->expand(values), eckit::BadValue); } void expandKey(const std::string& key, std::vector values, std::vector expected) { static metkit::mars::MarsLanguage language("retrieve"); metkit::mars::Type* t = language.type(key); t->expand(values); EXPECT_EQUAL(expected, values); } void quantileThrows(std::vector values) { expandKeyThrows("quantile", values); } void quantile(std::vector values, std::vector expected) { expandKey("quantile", values, expected); } CASE("test_metkit_expand_11_quantile") { quantileThrows({"-1:5"}); quantileThrows({"0:-5"}); quantileThrows({"6:5"}); quantileThrows({"0:12"}); quantile({"2:5"}, {"2:5"}); quantile({"0:2", "1:2", "2:2"}, {"0:2", "1:2", "2:2"}); quantile({"0:2", "1:3", "2:5"}, {"0:2", "1:3", "2:5"}); quantileThrows({"to", "5:10"}); quantileThrows({"3:5", "to"}); quantileThrows({"3:5", "to", "5:10"}); quantileThrows({"1:5", "to", "3:5", "by"}); quantile({"0:5", "to", "0:5"}, {"0:5"}); quantile({"3:3", "to", "3:3"}, {"3:3"}); quantile({"0:5", "to", "5:5"}, {"0:5", "1:5", "2:5", "3:5", "4:5", "5:5"}); quantile({"0:5", "to", "5:5", "by", "1"}, {"0:5", "1:5", "2:5", "3:5", "4:5", "5:5"}); quantile({"0:5", "to", "5:5", "by", "2"}, {"0:5", "2:5", "4:5"}); quantile({"0:5", "to", "5:5", "by", "3"}, {"0:5", "3:5"}); quantile({"0:5", "to", "5:5", "by", "5"}, {"0:5", "5:5"}); quantile({"0:5", "to", "5:5", "by", "6"}, {"0:5"}); quantile({"2:5", "to", "5:5", "by", "2"}, {"2:5", "4:5"}); quantile({"3:5", "to", "5:5", "by", "2"}, {"3:5", "5:5"}); quantile({"4:5", "to", "5:5", "by", "2"}, {"4:5"}); quantile({"0:10", "3:10", "to", "7:10", "by", "2", "10:10"}, {"0:10", "3:10", "5:10", "7:10", "10:10"}); quantile({"3:5", "to", "2:5"}, {"3:5", "2:5"}); } void timeThrows(std::vector values) { expandKeyThrows("time", values); } void time(std::vector values, std::vector expected) { expandKey("time", values, expected); } CASE("test_metkit_expand_12_time") { timeThrows({"87"}); timeThrows({"000012"}); timeThrows({"0:0:12"}); timeThrows({"12s"}); time({"0"}, {"0000"}); time({"0", "1", "6", "12", "18"}, {"0000", "0100", "0600", "1200", "1800"}); time({"0", "1", "12"}, {"0000", "0100", "1200"}); time({"0030"}, {"0030"}); time({"30m"}, {"0030"}); time({"00:30", "1:30", "02:50"}, {"0030", "0130", "0250"}); time({"0h", "3h", "120m", "170m"}, {"0000", "0300", "0200", "0250"}); timeThrows({"to", "5"}); timeThrows({"3", "to"}); timeThrows({"1", "to", "3", "by"}); time({"0", "to", "0"}, {"0000"}); time({"12", "to", "12"}, {"1200"}); time({"0", "to", "12"}, {"0000", "0600", "1200"}); time({"3", "to", "2"}, {"0300"}); time({"12", "to", "4"}, {"1200", "0600"}); time({"0", "to", "6", "by", "1"}, {"0000", "0100", "0200", "0300", "0400", "0500", "0600"}); time({"0", "to", "6", "by", "2"}, {"0000", "0200", "0400", "0600"}); time({"0", "to", "6", "by", "3"}, {"0000", "0300", "0600"}); time({"0", "to", "6", "by", "4"}, {"0000", "0400"}); time({"0", "to", "6", "by", "5"}, {"0000", "0500"}); time({"0", "to", "6", "by", "6"}, {"0000", "0600"}); time({"6", "to", "18"}, {"0600", "1200", "1800"}); time({"1", "to", "6", "by", "1"}, {"0100", "0200", "0300", "0400", "0500", "0600"}); time({"1", "to", "6", "by", "2"}, {"0100", "0300", "0500"}); time({"1", "to", "6", "by", "3"}, {"0100", "0400"}); time({"1", "to", "6", "by", "4"}, {"0100", "0500"}); time({"1", "to", "6", "by", "5"}, {"0100", "0600"}); time({"1", "to", "6", "by", "6"}, {"0100"}); time({"1", "to", "3h", "by", "30m"}, {"0100", "0130", "0200", "0230", "0300"}); } void stepThrows(std::vector values) { expandKeyThrows("step", values); } void step(std::string valuesStr, std::string expectedStr) { eckit::Tokenizer parse("/"); std::vector values; std::vector expected; parse(valuesStr, values); parse(expectedStr, expected); expandKey("step", values, expected); } CASE("test_metkit_expand_13_step") { step("0", "0"); step("1", "1"); step("24", "24"); step("144", "144"); step("012", "12"); step("12:30", "12h30m"); step("1:00", "1"); step("1:0:0", "1"); step("1h", "1"); step("60m", "1"); step("1h60m", "2"); step("0:5", "5m"); step("0:05", "5m"); step("0:05:0", "5m"); step("0:06", "6m"); step("0:10", "10m"); step("0:12", "12m"); step("0:15", "15m"); step("0:20", "20m"); step("0:25", "25m"); step("0:30", "30m"); step("0:35", "35m"); step("0:40", "40m"); step("0:45", "45m"); step("0:50", "50m"); step("0:55", "55m"); step("0-24", "0-24"); step("0-24s", "0-24s"); step("0-120s", "0-2m"); step("0s-120m", "0-2"); step("1-2", "1-2"); step("30m-1", "30m-1"); step("30m-90m", "30m-1h30m"); step("0/to/24/by/3", "0/3/6/9/12/15/18/21/24"); step("12/to/48/by/12", "12/24/36/48"); step("12/to/47/by/12", "12/24/36"); step("40m/to/2/by/10m", "40m/50m/1/1h10m/1h20m/1h30m/1h40m/1h50m/2"); step("0/to/6/by/30m", "0/30m/1/1h30m/2/2h30m/3/3h30m/4/4h30m/5/5h30m/6"); step("0-6/to/18-24/by/6", "0-6/6-12/12-18/18-24"); step("0-24/to/48-72/by/24", "0-24/24-48/48-72"); step("0/to/24/by/3/0-6/to/18-24/by/6", "0/3/6/9/12/15/18/21/24/0-6/6-12/12-18/18-24"); step("0-24/to/24-48/by/90m", "0-24/1h30m-25h30m/3-27/4h30m-28h30m/6-30/7h30m-31h30m/9-33/10h30m-34h30m/12-36/13h30m-37h30m/15-39/" "16h30m-40h30m/18-42/19h30m-43h30m/21-45/22h30m-46h30m/24-48"); } void activity(std::vector values, std::vector expected) { expandKey("activity", values, expected); } void experiment(std::vector values, std::vector expected) { expandKey("experiment", values, expected); } void model(std::vector values, std::vector expected) { expandKey("model", values, expected); } CASE("test_metkit_expand_lowercase") { activity({"ScenarioMIP"}, {"scenariomip"}); activity({"CMIP6"}, {"cmip6"}); activity({"ScenarioMIP"}, {"scenariomip"}); activity({"cmip6"}, {"cmip6"}); experiment({"SSP3-7.0"}, {"ssp3-7.0"}); experiment({"ssp3-7.0"}, {"ssp3-7.0"}); experiment({"hist"}, {"hist"}); model({"IFS-NEMO"}, {"ifs-nemo"}); model({"IFS"}, {"ifs"}); model({"ifs-nemo"}, {"ifs-nemo"}); model({"ifs"}, {"ifs"}); model({"ICON"}, {"icon"}); model({"icon"}, {"icon"}); } CASE("test_metkit_expand_param") { { const char* text = "retrieve,class=od,expver=0079,stream=enfo,date=-1,time=00/12,type=pf,levtype=sfc,step=24,number=1/to/" "2,param=mucin/mucape/tprate"; MarsRequest r = MarsRequest::parse(text); auto params = r.values("param"); EXPECT_EQUAL(params.size(), 3); EXPECT_EQUAL(params[0], "228236"); EXPECT_EQUAL(params[1], "228235"); EXPECT_EQUAL(params[2], "260048"); } { const char* text = "retrieve,class=od,expver=0079,stream=enfh,date=-1,time=00/12,type=fcmean,levtype=sfc,step=24,number=1/to/" "2,param=mucin/mucape/tprate"; MarsRequest r = MarsRequest::parse(text); auto params = r.values("param"); EXPECT_EQUAL(params.size(), 3); EXPECT_EQUAL(params[0], "228236"); EXPECT_EQUAL(params[1], "228235"); EXPECT_EQUAL(params[2], "172228"); } { const char* text = "retrieve,class=od,expver=1,stream=wave,date=-1,time=00/12,type=an,levtype=sfc,step=24,param=2dfd "; MarsRequest r = MarsRequest::parse(text); auto params = r.values("param"); EXPECT_EQUAL(params.size(), 1); EXPECT_EQUAL(params[0], "140251"); } { const char* text = "retrieve,class=od,expver=1,stream=enwh,date=-1,time=00/12,type=cf,levtype=sfc,step=24,param=tmax"; MarsRequest r = MarsRequest::parse(text); auto params = r.values("param"); EXPECT_EQUAL(params.size(), 1); EXPECT_EQUAL(params[0], "140217"); } { const char* text = "retrieve,class=ai,expver=1,stream=oper,model=aifs-singlw,date=-1,time=00/" "12,type=pf,levtype=pl,step=24,param=t"; EXPECT_THROWS_AS(MarsRequest::parse(text, true), eckit::UserError); } { const char* text = "retrieve,class=ai,expver=1,stream=oper,model=aifs-single,date=-1,time=00/" "12,type=pf,levtype=pl,step=24,param=t"; MarsRequest r = MarsRequest::parse(text); auto params = r.values("param"); EXPECT_EQUAL(params.size(), 1); EXPECT_EQUAL(params[0], "130"); } { const char* text = "retrieve,class=od,date=20240723,domain=g,expver=0079,levtype=sfc,param=asn/cp/lsp/sf/tcc/" "tp,step=0,stream=oper,time=0000,type=fc"; MarsRequest r = MarsRequest::parse(text); auto params = r.values("param"); EXPECT_EQUAL(params.size(), 6); EXPECT_EQUAL(params[0], "32"); EXPECT_EQUAL(params[1], "143"); EXPECT_EQUAL(params[2], "142"); EXPECT_EQUAL(params[3], "144"); EXPECT_EQUAL(params[4], "164"); EXPECT_EQUAL(params[5], "228"); } { const char* text = "retrieve,class=od,expver=1,stream=msmm,date=-1,time=0000,type=em,levtype=sfc,step=24,param=e"; MarsRequest r = MarsRequest::parse(text); auto params = r.values("param"); EXPECT_EQUAL(params.size(), 1); EXPECT_EQUAL(params[0], "172182"); } { const char* text = "retrieve,class=od,expver=1,stream=msmm,date=-1,time=0000,type=em,levtype=sfc,step=24,param=e/erate"; MarsRequest r = MarsRequest::parse(text); auto params = r.values("param"); EXPECT_EQUAL(params.size(), 2); EXPECT_EQUAL(params[0], "172182"); EXPECT_EQUAL(params[1], "172182"); } { const char* text = "retrieve,class=od,expver=1,stream=enwh,date=-1,time=0000,type=pf,levtype=sfc,step=24,param=sh10"; MarsRequest r = MarsRequest::parse(text); auto params = r.values("param"); EXPECT_EQUAL(params.size(), 1); EXPECT_EQUAL(params[0], "140120"); } { const char* text = "retrieve,class=od,expver=1,stream=enwh,date=-1,time=0000,type=pf,levtype=sfc,step=24,param=p1ww"; MarsRequest r = MarsRequest::parse(text); auto params = r.values("param"); EXPECT_EQUAL(params.size(), 1); EXPECT_EQUAL(params[0], "140223"); } { const char* text = "retrieve,class=od,expver=1,stream=waef,date=-1,time=0000,type=cf,levtype=sfc,step=24,param=WSK/MWP"; MarsRequest r = MarsRequest::parse(text); auto params = r.values("param"); EXPECT_EQUAL(params.size(), 2); EXPECT_EQUAL(params[0], "140252"); EXPECT_EQUAL(params[1], "140232"); } { const char* text = "retrieve,class=od,expver=1,stream=eefo,date=-1,time=0000,type=fcmean,levtype=sfc,step=24,param=MSL"; MarsRequest r = MarsRequest::parse(text); auto params = r.values("param"); EXPECT_EQUAL(params.size(), 1); EXPECT_EQUAL(params[0], "151"); } { const char* text = "retrieve,class=od,expver=1,stream=eefo,date=-1,time=0000,type=fcmean,levtype=sfc,step=24,param=strda"; MarsRequest r = MarsRequest::parse(text); auto params = r.values("param"); EXPECT_EQUAL(params.size(), 1); EXPECT_EQUAL(params[0], "171175"); } } CASE("test_metkit_expand_d1") { { const char* text = "retrieve,class=d1,dataset=extremes-dt,date=-1"; ExpectedVals expected{{"class", {"d1"}}, {"dataset", {"extremes-dt"}}, {"expver", {"0001"}}, {"levelist", {"1000", "850", "700", "500", "400", "300"}}, {"levtype", {"pl"}}, {"param", {"129"}}, {"step", {"0"}}, {"stream", {"oper"}}, {"time", {"1200"}}, {"type", {"an"}}}; expand(text, "retrieve", expected, {-1}); } { const char* text = "retrieve,class=d1,dataset=climate-dt,levtype=pl,date=20000101,activity=CMIP6,experiment=hist,model=IFS-" "NEMO,generation=1,realization=1,resolution=high,stream=clte,type=fc,param=134/137"; ExpectedVals expected{{"class", {"d1"}}, {"dataset", {"climate-dt"}}, {"activity", {"cmip6"}}, {"experiment", {"hist"}}, {"model", {"ifs-nemo"}}, {"generation", {"1"}}, {"realization", {"1"}}, {"resolution", {"high"}}, {"expver", {"0001"}}, {"time", {"1200"}}, {"stream", {"clte"}}, {"type", {"fc"}}, {"levtype", {"pl"}}, {"levelist", {"1000", "850", "700", "500", "400", "300"}}, {"param", {"134", "137"}}}; expand(text, "retrieve", expected, {20000101}); } { const char* text = "retrieve,date=20120515,time=0000,dataset=climate-dt,activity=cmip6,experiment=hist,generation=1,model=" "icon,realization=1,georef=acbdef,resolution=high,class=d1,expver=0001,type=fc,stream=clte,levelist=1," "levtype=o3d,param=263500"; const char* text2 = "retrieve,date=20120515,time=0000,dataset=climate-dt,activity=cmip6,experiment=hist,generation=1,model=" "icon,realization=1,resolution=high,class=d1,expver=0001,type=fc,stream=clte,levelist=1," "levtype=o3d,param=263500"; ExpectedVals expected{{"class", {"d1"}}, {"dataset", {"climate-dt"}}, {"activity", {"cmip6"}}, {"experiment", {"hist"}}, {"model", {"icon"}}, {"generation", {"1"}}, {"realization", {"1"}}, {"resolution", {"high"}}, {"expver", {"0001"}}, {"time", {"0000"}}, {"stream", {"clte"}}, {"type", {"fc"}}, {"levtype", {"o3d"}}, {"levelist", {"1"}}, {"param", {"263500"}}}; expand(text, "retrieve", expected, {20120515}); expand(text2, "retrieve", expected, {20120515}); } } CASE("test_metkit_expand_ng") { { const char* text = "retrieve,class=ng,date=20000101,activity=CMIP6,experiment=hist,model=IFS-NEMO,generation=1,realization=1," "resolution=high,stream=clte,type=fc,levtype=pl,param=134/137"; ExpectedVals expected{{"class", {"ng"}}, {"levtype", {"pl"}}, {"levelist", {"1000", "850", "700", "500", "400", "300"}}, {"activity", {"cmip6"}}, {"experiment", {"hist"}}, {"model", {"ifs-nemo"}}, {"generation", {"1"}}, {"realization", {"1"}}, {"resolution", {"high"}}, {"expver", {"0001"}}, {"date", {"20000101"}}, {"time", {"1200"}}, {"stream", {"clte"}}, {"type", {"fc"}}, {"param", {"134", "137"}}}; expand(text, "retrieve", expected, {20000101}); } } CASE("test_metkit_expand_ai") { { const char* text = "retrieve,class=ai,date=20250208,time=1800,expver=9999,model=aifs-single,type=fc,levtype=sfc,param=169"; ExpectedVals expected{{"class", {"ai"}}, {"domain", {"g"}}, {"expver", {"9999"}}, {"levtype", {"sfc"}}, {"step", {"0"}}, {"stream", {"oper"}}, {"time", {"1800"}}, {"type", {"fc"}}, {"model", {"aifs-single"}}, {"param", {"169"}}}; expand(text, "retrieve", expected, {20250208}); } } CASE("test_metkit_expand_list") { { const char* text = "list,date=20250105,domain=g,levtype=pl,expver=" "0001,step=0,stream=oper,levelist=1000/850/700/500/400/" "300,time=1200,type=an,param=129"; ExpectedVals expected{{"class", {"od"}}, {"date", {"20250105"}}, {"domain", {"g"}}, {"levtype", {"pl"}}, {"levelist", {"1000", "850", "700", "500", "400", "300"}}, {"expver", {"0001"}}, {"time", {"1200"}}, {"stream", {"oper"}}, {"type", {"an"}}, {"param", {"129"}}}; expand(text, "list", expected, {20250105}); } { const char* text = "list,class=tr,date=20250105"; ExpectedVals expected{{"class", {"tr"}}, {"date", {"20250105"}}}; expand(text, "list", expected, {20250105}); } } CASE("test_metkit_expand_read") { { const char* text = "read,class=tr,date=20250105,domain=g,levtype=pl,expver=0001,step=0,stream=oper," "levelist=1000/850/700/500/400/300,time=1200,type=an,param=129"; ExpectedVals expected{{"class", {"tr"}}, {"date", {"20250105"}}, {"domain", {"g"}}, {"levtype", {"pl"}}, {"levelist", {"1000", "850", "700", "500", "400", "300"}}, {"expver", {"0001"}}, {"time", {"1200"}}, {"stream", {"oper"}}, {"type", {"an"}}, {"param", {"129"}}}; expand(text, "read", expected, {20250105}); } { const char* text = "read,date=20250105,param=129"; ExpectedVals expected{{"date", {"20250105"}}, {"param", {"129"}}}; expand(text, "read", expected, {20250105}); } } CASE("test_metkit_expand_clmn") { { const char* text = "retrieve,class=d1,expver=1,dataset=climate-dt,activity=story-nudging,experiment=Tplus2.0K,generation=1," "model=IFS-FESOM,realization=1,stream=clmn,year=2024,month=october,resolution=standard,type=fc,levtype=sfc," "param=144"; ExpectedVals expected{{"class", {"d1"}}, {"dataset", {"climate-dt"}}, {"activity", {"story-nudging"}}, {"experiment", {"tplus2.0k"}}, {"generation", {"1"}}, {"model", {"ifs-fesom"}}, {"realization", {"1"}}, {"expver", {"0001"}}, {"stream", {"clmn"}}, {"year", {"2024"}}, {"month", {"10"}}, {"resolution", {"standard"}}, {"type", {"fc"}}, {"levtype", {"sfc"}}, {"param", {"144"}}}; expand(text, "retrieve", expected, {}); } } CASE("test_metkit_expand_chem") { const char* text = "retrieve,chem=co/no2/no/so2,class=mc,date=2006-12-18,expver=9001,levtype=sfc,param=402000,step=12,stream=oper," "time=00:00:00,type=fc,target=\"output\""; const char* expected = "RETRIEVE,CLASS=MC,TYPE=FC,STREAM=OPER,EXPVER=9001,LEVTYPE=SFC,PARAM=402000,CHEM=2/17/27/233,DATE=20061218," "TIME=0000,STEP=12,DOMAIN=G,TARGET=output"; expand(text, expected); } CASE("test_metkit_expand_frequency") { const char* text = "retrieve,class=od,date=20250401,direction=31,domain=g,expver=0001,frequency=7,levtype=sfc,param=140217,step=0," "stream=wave,time=1200,type=an"; const char* expected = "RETRIEVE,CLASS=OD,TYPE=AN,STREAM=WAVE,EXPVER=0001,REPRES=SH,LEVTYPE=SFC,PARAM=140217,DATE=20250401,TIME=1200," "STEP=0,DOMAIN=G,FREQUENCY=7,DIRECTION=31"; expand(text, expected); } // issues from https://confluence.ecmwf.int/pages/viewpage.action?pageId=496866851 CASE("test_metkit_expand_MARSC-218") { // https://jira.ecmwf.int/browse/MARSC-218 const char* text = "retrieve,accuracy=10,class=ea,date=1969-03-28,expver=11,grid=0.25/" "0.25,levtype=sfc,packing=si,param=142.128/143.128/151.128/165.128/166.128,step=0/6/12/18/24/30/36/42/48/" "54/60/66/72/78/84/90/96/102/108/114/120/132/144/156/168/180/192/204/216/228/" "240,stream=oper,time=00:00:00,type=fc,target=\"reference.rFP7XB.data\""; const char* expected = "RETRIEVE,CLASS=EA,TYPE=FC,STREAM=OPER,EXPVER=0011,LEVTYPE=SFC,PARAM=142/143/151/165/" "166,DATE=19690328,TIME=0000,STEP=0/6/12/18/24/30/36/42/48/54/60/66/72/78/84/90/96/102/108/114/120/132/144/" "156/168/180/192/204/216/228/240,DOMAIN=G,TARGET=reference.rFP7XB.data,RESOL=AUTO,ACCURACY=10,GRID=.25/" ".25,PACKING=SIMPLE"; expand(text, expected); } CASE("test_metkit_expand_MARSC-221") { // https://jira.ecmwf.int/browse/MARSC-221 const char* text = "retrieve,accuracy=12,area=90.0/0.0/-90.0/359.5,date=20240102,domain=g,grid=0.5/" "0.5,leve=off,levtype=sfc,padding=0,param=134/137/165/166/167/168/" "235,stream=da,style=dissemination,time=00,type=an,target=\"reference.tzpUX7.data\""; const char* expected = "RETRIEVE,CLASS=OD,TYPE=AN,STREAM=OPER,EXPVER=0001,REPRES=GG,LEVTYPE=SFC,PARAM=134/137/165/166/167/168/" "235,DATE=20240102,TIME=0000,STEP=0,DOMAIN=G,TARGET=reference.tzpUX7.data,RESOL=AV,ACCURACY=12,STYLE=" "DISSEMINATION,AREA=90/0/-90/359.5,GRID=.5/.5,PADDING=0"; expand(text, expected); } CASE("test_metkit_expand_MARSC-212") { // https://jira.ecmwf.int/browse/MARSC-212 const char* text = "retrieve,accuracy=16,area=14.8/-19.6/-14.5/19.8,class=od,date=20230810,expver=1,grid=0.09/0.09,levelist=1/" "to/137,levtype=ml,number=-1,param=z,process=local,rotation=-78.8/-61.0,step=000,stream=scda,time=18," "type=an,target=\"reference.ect1qF.data\""; const char* expected = "RETRIEVE,CLASS=OD,TYPE=AN,STREAM=SCDA,EXPVER=0001,REPRES=SH,LEVTYPE=ML,LEVELIST=1/2/3/4/5/6/7/8/9/10/11/" "12/13/14/15/16/17/18/19/20/21/22/23/24/25/26/27/28/29/30/31/32/33/34/35/36/37/38/39/40/41/42/43/44/45/46/" "47/48/49/50/51/52/53/54/55/56/57/58/59/60/61/62/63/64/65/66/67/68/69/70/71/72/73/74/75/76/77/78/79/80/81/" "82/83/84/85/86/87/88/89/90/91/92/93/94/95/96/97/98/99/100/101/102/103/104/105/106/107/108/109/110/111/112/" "113/114/115/116/117/118/119/120/121/122/123/124/125/126/127/128/129/130/131/132/133/134/135/136/137," "PARAM=129,DATE=20230810,TIME=1800,STEP=0,DOMAIN=G,TARGET=reference.ect1qF.data,RESOL=AUTO,ACCURACY=16," "AREA=14.8/-19.6/-14.5/19.8,ROTATION=-78.8/-61,GRID=.09/.09,PROCESS=LOCAL"; expand(text, expected); } CASE("test_metkit_expand_MARSC-210") { // https://jira.ecmwf.int/browse/MARSC-210 const char* text = "retrieve,accuracy=24,area=90.0/-179.0/-90.0/180.0,class=od,dataset=none,date=20231231/to/20231231,expver=1," "grid=off,levelist=1,levtype=ml,number=off,padding=0,param=152.128,resol=255,step=00,stream=oper,time=00/12," "type=an,target=reference.data"; const char* expected = "RETRIEVE,DATASET=none,CLASS=OD,TYPE=AN,STREAM=OPER,EXPVER=0001,REPRES=SH,LEVTYPE=ML,LEVELIST=1,PARAM=152," "DATE=20231231,TIME=0000/1200,STEP=0,DOMAIN=G,TARGET=reference.data,RESOL=255,ACCURACY=24," "AREA=90/-179/-90/180,PADDING=0"; expand(text, expected); } CASE("test_metkit_expand_MARSC-220") { // https://jira.ecmwf.int/browse/MARSC-220 // the original request contains an_offet which is not supported, and has been replaced by anoffset const char* text = "retrieve,anoffset=9,class=rd,date=20210828,expver=i8k5,gaussian=regular,grid=4000,levtype=sfc,param=151." "128/165.128/166.128,step=15,stream=da,time=00,type=fc,target=\"reference.6Zr8N7.data\""; const char* expected = "RETRIEVE,CLASS=RD,TYPE=FC,STREAM=OPER,EXPVER=i8k5,REPRES=SH,LEVTYPE=SFC,PARAM=151/165/" "166,DATE=20210828,TIME=0000,STEP=15,DOMAIN=G,TARGET=reference.6Zr8N7.data,RESOL=AUTO,GRID=F4000"; expand(text, expected); } CASE("test_metkit_expand_MARSC-214") { // https://jira.ecmwf.int/browse/MARSC-214 const char* text = "retrieve,anoffset=90,class=ce,database=marser,date=20240102,domain=g,expver=0001,level=3,levtype=sol," "model=lisflood,origin=ecmf,param=260199,step=6/to/72/by/" "6,stream=efas,time=0000,type=sfo,expect=any,target=\"reference.43PsBL.data\""; const char* expected = "RETRIEVE,CLASS=CE,TYPE=SFO,STREAM=EFAS,EXPVER=0001,MODEL=lisflood,REPRES=SH,LEVTYPE=SOL,LEVELIST=3,PARAM=" "260199,DATE=20240102,TIME=0000,STEP=6/12/18/24/30/36/42/48/54/60/66/" "72,ANOFFSET=90,DOMAIN=G,ORIGIN=ECMF,EXPECT=ANY,TARGET=reference.43PsBL.data,DATABASE=marser"; expand(text, expected); } CASE("test_metkit_expand_MARSC-222") { // https://jira.ecmwf.int/browse/MARSC-222 const char* text = "retrieve,class=rd,date=20201204,expver=hk3a,obsgroup=22,reportype=21001,stream=lwda,time=1200,type=mfb," "target=\"reference.vYyJf6.data\""; /// @todo DUPLICATES const char* expected = "RETRIEVE,CLASS=RD,TYPE=MFB,STREAM=LWDA,EXPVER=hk3a,REPRES=BU,OBSGROUP=AMSUA_AS,REPORTYPE=21001,obstype=1," "DATE=20201204,TIME=1200,DOMAIN=G,TARGET=reference.vYyJf6.data,DUPLICATES=KEEP"; // expand(text, expected); } CASE("test_metkit_expand_MARSC-219") { // https://jira.ecmwf.int/browse/MARSC-219 const char* text = "retrieve,class=od,date=20231205,expver=0001,obstype=gpsro,stream=lwda,time=18,type=ai,target=\"reference." "E2RRc8.data\""; const char* expected = // "RETRIEVE,CLASS=OD,TYPE=AI,STREAM=LWDA,EXPVER=0001,REPRES=BU,OBSTYPE=250,DATE=20231205,TIME=1800,DOMAIN=G," // "TARGET=reference.E2RRc8.data,DUPLICATES=KEEP"; "RETRIEVE,CLASS=OD,TYPE=AI,STREAM=LWDA,EXPVER=0001,OBSTYPE=250,DATE=20231205,TIME=1800,DOMAIN=G," "TARGET=reference.E2RRc8.data,DUPLICATES=KEEP"; expand(text, expected); } CASE("test_metkit_expand_MARSC-213") { // https://jira.ecmwf.int/browse/MARSC-213 const char* text = "retrieve,class=od,date=20230821,expect=any,expver=0001,levtype=sfc,param=70.228/71.228/72.228/73.228/" "74.228,stream=da,time=12,type=gai,target=\"reference.1e7AY1.data\""; const char* expected = "RETRIEVE,CLASS=OD,TYPE=GAI,STREAM=OPER,EXPVER=0001,REPRES=GG,LEVTYPE=SFC,PARAM=228070/228071/228072/" "228073/228074,DATE=20230821,TIME=1200,STEP=0,DOMAIN=G,TARGET=reference.1e7AY1.data,EXPECT=ANY"; expand(text, expected); } CASE("test_metkit_expand_MARSC-211") { // https://jira.ecmwf.int/browse/MARSC-211 const char* text = "retrieve,class=ce,database=marser,date=20240102,domain=g,expver=0001,level=2,levtype=sol,model=lisflood," "origin=ecmf,param=260199,step=6/to/240/by/" "6,stream=efas,time=0000,type=fc,target=\"reference.JkqWoW.data\""; const char* expected = "RETRIEVE,CLASS=CE,TYPE=FC,STREAM=EFAS,EXPVER=0001,MODEL=lisflood,REPRES=SH,LEVTYPE=SOL,LEVELIST=2,PARAM=" "260199,DATE=20240102,TIME=0000,STEP=6/12/18/24/30/36/42/48/54/60/66/72/78/84/90/96/102/108/114/120/126/" "132/138/144/150/156/162/168/174/180/186/192/198/204/210/216/222/228/234/" "240,DOMAIN=G,ORIGIN=ECMF,TARGET=reference.JkqWoW.data"; expand(text, expected); } CASE("test_metkit_expand_MARSC-243") { // https://jira.ecmwf.int/browse/MARSC-243 const char* text = "retrieve,DOMAIN=G,LEVTYPE=PL,LEVELIST=200,DATE=20040114,TIME=0000,PARAM=155.128,CLASS=OD,TYPE=FCMEAN,STREAM=" "MOFM,EXPVER=0001,NUMBER=0,SYSTEM=2,METHOD=1,FCPERIOD=5-11,target=\"reference.GP8yZ1.data\""; const char* expected = "RETRIEVE,CLASS=OD,TYPE=FCMEAN,STREAM=MOFM,EXPVER=0001,REPRES=SH,LEVTYPE=PL,LEVELIST=200,PARAM=155,DATE=" "20040114,FCPERIOD=5-11,TIME=0000,NUMBER=0,DOMAIN=G,SYSTEM=2,METHOD=1,TARGET=reference.GP8yZ1.data"; expand(text, expected); } CASE("test_metkit_expand_MARSC-246") { // https://jira.ecmwf.int/browse/MARSC-246 const char* text = "retrieve,DOMAIN=G,LEVTYPE=DP,DATE=20120201,TIME=0000,STEP=288,PARAM=175.151,CLASS=OD,TYPE=OF,STREAM=OCEA," "EXPVER=0001,NUMBER=0,SYSTEM=3,METHOD=1,PRODUCT=TIMS,SECTION=Z,LEVELIST=0.000,LATITUDE=-9.967,RANGE=264,target=" "\"reference.t2APXu.data\""; const char* expected = "RETRIEVE,CLASS=OD,TYPE=OF,STREAM=OCEA,EXPVER=0001,REPRES=SH,LEVTYPE=DP,LEVELIST=0,PARAM=151175,DATE=20120201," "TIME=0000,RANGE=264,STEP=288,NUMBER=0,DOMAIN=G,SYSTEM=3,METHOD=1,PRODUCT=TIMS,SECTION=Z,LATITUDE=-9.967," "TARGET=reference.t2APXu.data"; expand(text, expected); } CASE("test_metkit_expand_MARSC-253") { // https://jira.ecmwf.int/browse/MARSC-253 const char* text = "retrieve,class=od,type=tf,stream=enfo,expver=0001,repres=bu,obstype=32,date=20060112,time=0000/" "1200,domain=g,duplicates=keep,target=\"data.reference\""; const char* expected = "RETRIEVE,CLASS=OD,TYPE=TF,STREAM=ENFO,EXPVER=0001,REPRES=BU,OBSTYPE=32,DATE=20060112,TIME=0000/" "1200,STEP=0,DOMAIN=G,TARGET=data.reference,DUPLICATES=KEEP"; expand(text, expected); } CASE("test_metkit_expand_MARSC-254") { // https://jira.ecmwf.int/browse/MARSC-254 const char* text = "retrieve,type=ob,date=20250414,time=00,range=1439,target=\"data.reference\""; const char* expected = "RETRIEVE,CLASS=OD,TYPE=OB,STREAM=OPER,EXPVER=0001,REPRES=BU,OBSTYPE=1,DATE=20250414,TIME=0000,RANGE=1439," "DOMAIN=G,TARGET=data.reference,DUPLICATES=KEEP"; expand(text, expected); } // https://jira.ecmwf.int/browse/MARSC-306 CASE("test_metkit_expand_MARSC-306") { const std::string text = "retrieve,CLASS=OD,TYPE=PF,STREAM=EF,EXPVER=0001,REPRES=SH,LEVTYPE=SFC,PARAM=167/165/166/164/" "228,DATE=20250523,TIME=0000,STEP=6/12,NUMBER=1/2,DOMAIN=G,RESOL=N128,AREA=70.5/-21.0/30.0/40.5,GRID=1.5/" "1.5,target=\"target.vareps.test\",RESOL=N128"; // N128 needs to be forwarded and is therefore not manipulated const std::string expected = "retrieve,class=od,type=pf,stream=enfo,levtype=sfc,date=20250523,time=0000,step=6/" "12,expver=0001,domain=g,number=1/2,param=167/165/166/164/228,target=target.vareps.test,grid=1.5/1.5,area=70.5/" "-21/30/40.5,repres=sh,resol=N128"; expand(text, expected); } // https://jira.ecmwf.int/browse/MARSC-433 CASE("test_metkit_expand_MARSC-433") { const std::string text = "retrieve,CLASS=EA,DATE=20061212,DOMAIN=G,EXPVER=0001,LEVELIST=1/2/" "3,LEVTYPE=ML,PARAM=152,REPRES=SH,RESOL=199,STREAM=DA,TIME=00/06/12/18,TYPE=AN"; const std::string expected = "retrieve,CLASS=EA,DATE=20061212,DOMAIN=G,EXPVER=0001,LEVELIST=1/2/" "3,LEVTYPE=ML,PARAM=152,REPRES=SH,truncation=199,STREAM=oper,TIME=0000/0600/1200/1800,TYPE=AN"; expand(text, expected); } CASE("test_metkit_expand_resol") { { const std::string text = "retrieve,class=ea,date=20061212,domain=g,expver=1,levelist=1/2/" "3,levtype=ml,param=152,repres=sh,resol=av,stream=da,time=00/06/12/18,type=an"; const std::string expected = "retrieve,class=ea,date=20061212,domain=g,expver=0001,levelist=1/2/" "3,levtype=ml,param=152,repres=sh,intgrid=source,truncation=none,stream=oper,time=0000/0600/1200/" "1800,type=an"; expand(text, expected); } { const std::string text = "retrieve,class=ea,date=20061213,domain=g,expver=1,levelist=1/2/" "3,levtype=ml,param=152,repres=sh,resol=N128,stream=da,time=00/06/12/18,type=an"; const std::string expected = "retrieve,class=ea,date=20061213,domain=g,expver=0001,levelist=1/2/" "3,levtype=ml,param=152,repres=sh,intgrid=N128,stream=oper,time=0000/0600/1200/1800,type=an"; expand(text, expected); } } CASE("test_metkit_expand_coeffindex") { { const char* text = "retrieve,class=rd,coeffindex=1/to/3,date=2026-01-01,expver=1,levelist=1,levtype=ml,param=130/131/132/138/" "139/152/155,step=0,number=1,stream=oper,time=09:00:00,type=me,target=output"; const char* expected = "retrieve,class=rd,coeffindex=1/2/3,date=20260101,expver=0001,levelist=1,levtype=ml,param=130/131/132/138/" "139/152/155,step=0,number=1,stream=oper,time=0900,type=me,target=output"; expand(text, expected); } { const char* text = "retrieve,class=od,coeffindex=1/to/3,date=2026-01-01,expver=1,levelist=1,levtype=ml,param=130/131/132/138/" "139/152/155,step=0,number=1,stream=oper,time=09:00:00,type=pf,target=output"; const char* expected = "retrieve,class=od,date=20260101,expver=0001,levelist=1,levtype=ml,param=130/131/132/138/139/152/" "155,step=0,number=1,stream=oper,time=0900,type=pf,target=output"; expand(text, expected); } } CASE("test_metkit_expand_0") { const char* text = "retrieve,accuracy=16,area=14.8/-19.6/-14.5/19.8,class=od,date=20230810,expver=1,grid=0.09/0.09,levelist=1/" "to/137,levtype=ml,number=-1,param=z,process=local,rotation=-78.8/" "-61.0,step=000,stream=scda,time=18,type=an,target=\"reference.ect1qF.data\""; const char* expected = "RETRIEVE,CLASS=OD,TYPE=AN,STREAM=SCDA,EXPVER=0001,REPRES=SH,LEVTYPE=ML,LEVELIST=1/2/3/4/5/6/7/8/9/10/11/" "12/13/14/15/16/17/18/19/20/21/22/23/24/25/26/27/28/29/30/31/32/33/34/35/36/37/38/39/40/41/42/43/44/45/46/" "47/48/49/50/51/52/53/54/55/56/57/58/59/60/61/62/63/64/65/66/67/68/69/70/71/72/73/74/75/76/77/78/79/80/81/" "82/83/84/85/86/87/88/89/90/91/92/93/94/95/96/97/98/99/100/101/102/103/104/105/106/107/108/109/110/111/112/" "113/114/115/116/117/118/119/120/121/122/123/124/125/126/127/128/129/130/131/132/133/134/135/136/" "137,PARAM=129,DATE=20230810,TIME=1800,STEP=0,DOMAIN=G,TARGET=reference.ect1qF.data,RESOL=AUTO,ACCURACY=16," "AREA=14.8/-19.6/-14.5/19.8,ROTATION=-78.8/-61,GRID=.09/.09,PROCESS=LOCAL"; expand(text, expected); } CASE("test_metkit_expand_1") { const char* text = "retrieve,accuracy=16,area=60.0/-60.0/-60.0/60.0,class=ea,date=20101029,expver=1,grid=0.30/0.30,levelist=1/" "to/137,levtype=ml,number=-1,param=q/t/u/v/lnsp/z,rotation=0.0/" "0.0,step=000,stream=oper,time=15:00:00,type=an,target=\"reference.1OEDK0.data\""; const char* expected = "RETRIEVE,CLASS=EA,TYPE=AN,STREAM=OPER,EXPVER=0001,LEVTYPE=ML,LEVELIST=1/2/3/4/5/6/7/8/9/10/11/12/13/14/15/" "16/17/18/19/20/21/22/23/24/25/26/27/28/29/30/31/32/33/34/35/36/37/38/39/40/41/42/43/44/45/46/47/48/49/50/" "51/52/53/54/55/56/57/58/59/60/61/62/63/64/65/66/67/68/69/70/71/72/73/74/75/76/77/78/79/80/81/82/83/84/85/" "86/87/88/89/90/91/92/93/94/95/96/97/98/99/100/101/102/103/104/105/106/107/108/109/110/111/112/113/114/115/" "116/117/118/119/120/121/122/123/124/125/126/127/128/129/130/131/132/133/134/135/136/137,PARAM=133/130/131/" "132/152/129,TIME=1500,STEP=0,DOMAIN=G,TARGET=reference.1OEDK0.data,RESOL=AUTO,ACCURACY=16,AREA=60/-60/-60/" "60,ROTATION=0/0,GRID=.3/.3,DATE=20101029"; expand(text, expected); } CASE("test_metkit_expand_2") { const char* text = "retrieve,accuracy=12,area=90.0/0.0/-90.0/359.5,date=20240102,domain=g,grid=0.5/" "0.5,leve=off,levtype=sfc,padding=0,param=134/137/165/166/167/168/" "235,stream=da,style=dissemination,time=00,type=an,target=\"reference.tzpUX7.data\""; const char* expected = "RETRIEVE,CLASS=OD,TYPE=AN,STREAM=OPER,EXPVER=0001,REPRES=GG,LEVTYPE=SFC,PARAM=134/137/165/166/167/168/" "235,DATE=20240102,TIME=0000,STEP=0,DOMAIN=G,TARGET=reference.tzpUX7.data,RESOL=AV,ACCURACY=12,STYLE=" "DISSEMINATION,AREA=90/0/-90/359.5,GRID=.5/.5,PADDING=0"; expand(text, expected); } CASE("test_metkit_disseminate") { const char* text = "disseminate,option=normal,target=NTI:HT,date=20250506,time=0/12,stream=oper,levtype=sfc,type=an,param=lsm," "step=0,direction=off,frequency=off,area=54.5/1.5/51/8,grid=.1/.1,packing=simple\n" "disseminate,stream=wave,param=2dfd,direction=1/to/36,frequency=1/to/29,packing=off\n" "disseminate,type=fc,step=3/to/144/by/3\n" "disseminate,stream=oper,type=an,param=lsm,step=0,direction=off,frequency=off,area=64/-15/43/13," "grid=.25/.25,packing=simple\n" "disseminate,stream=wave,param=tmax/hmax/swh/mwd/pp1d/mwp/shww/mdww/mpww/shts/mdts/mpts/sh10\n" "disseminate,type=fc,step=3/to/72/by/3\n" "disseminate,step=78/to/240/by/6"; std::vector expected = { "disseminate,stream=oper,type=an,param=172,step=0,area=54.5/1.5/51/8,grid=.1/.1,packing=simple,class=od," "date=20250506,domain=g,expver=0001,levtype=sfc,option=normal,target=NTI:HT,time=0000/1200", "disseminate,stream=wave,param=140251,direction=1/2/3/4/5/6/7/8/9/10/11/12/13/14/15/16/17/18/19/20/21/22/23/24/" "25/26/27/28/29/30/31/32/33/34/35/36,frequency=1/2/3/4/5/6/7/8/9/10/11/12/13/14/15/16/17/18/19/20/21/22/23/24/" "25/26/27/28/29,area=54.5/1.5/51/8,class=od,date=20250506,domain=g,expver=0001,grid=.1/.1,levtype=sfc," "option=normal,step=0,target=NTI:HT,time=0000/1200,type=an", "disseminate,type=fc,step=3/6/9/12/15/18/21/24/27/30/33/36/39/42/45/48/51/54/57/60/63/66/69/72/75/78/81/84/87/" "90/93/96/99/102/105/108/111/114/117/120/123/126/129/132/135/138/141/144,area=54.5/1.5/51/" "8,class=od,date=20250506,direction=1/2/3/4/5/6/7/8/9/10/11/12/13/14/15/16/17/18/19/20/21/22/23/24/25/26/27/28/" "29/30/31/32/33/34/35/36,domain=g,expver=0001,frequency=1/2/3/4/5/6/7/8/9/10/11/12/13/14/15/16/17/18/19/20/21/" "22/23/24/25/26/27/28/29,grid=.1/.1,levtype=sfc,option=normal,param=140251,stream=wave,target=NTI:HT,time=0000/" "1200", "disseminate,stream=oper,type=an,param=172,step=0,area=64/-15/43/13,grid=.25/" ".25,packing=simple,class=od,date=20250506,domain=g,expver=0001,levtype=sfc,option=normal,target=NTI:HT,time=" "0000/1200", "disseminate,stream=wave,param=140217/140218/140229/140230/140231/140232/140234/140235/140236/140237/140238/" "140239/140120,area=64/-15/43/13,class=od,date=20250506,domain=g,expver=0001,grid=.25/" ".25,levtype=sfc,option=normal,packing=simple,step=0,target=NTI:HT,time=0000/1200,type=an", "disseminate,type=fc,step=3/6/9/12/15/18/21/24/27/30/33/36/39/42/45/48/51/54/57/60/63/66/69/72,area=64/-15/43/" "13,class=od,date=20250506,domain=g,expver=0001,grid=.25/" ".25,levtype=sfc,option=normal,packing=simple,param=140217/140218/140229/140230/140231/140232/140234/140235/" "140236/140237/140238/140239/140120,stream=wave,target=NTI:HT,time=0000/1200", "disseminate,step=78/84/90/96/102/108/114/120/126/132/138/144/150/156/162/168/174/180/186/192/198/204/210/216/" "222/228/234/240,area=64/-15/43/13,class=od,date=20250506,domain=g,expver=0001,grid=.25/" ".25,levtype=sfc,option=normal,packing=simple,param=140217/140218/140229/140230/140231/140232/140234/140235/" "140236/140237/140238/140239/140120,stream=wave,target=NTI:HT,time=0000/1200,type=fc"}; expand(text, expected, false); } CASE("test_metkit_disseminate") { const char* text = "disseminate,stream=waef,levtype=sfc,param=131074,class=od,type=ep,date=20250918,time=1200,step=12,expver=0001," "domain=g,area=90/-180/-90/179.6,grid=.4/.4,target=OPN:DT"; std::vector expected = {text}; expand(text, expected, false); } CASE("test_metkit_disseminate_params-static") { const char* text = "disseminate,target=CAM:TT,option=normal,expver=0001,class=mc,stream=oper,date=20250807,time=0000,type=an,step=" "0,levtype=sfc,param=asn/hcc/mcc/sp/t/tcc"; std::vector expected = { "disseminate,class=mc,type=an,stream=oper,levtype=sfc,time=0000,step=0,expver=0001,param=32/188/187/134/130/" "164,option=normal,target=CAM:TT,date=20250807,domain=g"}; expand(text, expected, false); } CASE("test_metkit_files") { eckit::LocalPathName testFolder{"expand"}; ASSERT(testFolder.exists()); eckit::StdDir d(testFolder); for (;;) { struct dirent* e = d.dirent(); if (e == nullptr) { break; } if (::strstr(e->d_name, ".req")) { try { // look for the corresponding .expected file std::string reqFileName{testFolder / e->d_name}; eckit::PathName expFileName{reqFileName.substr(0, reqFileName.find_last_of('.')) + ".expected"}; ASSERT(expFileName.exists()); std::ifstream reqFile(reqFileName); std::stringstream req; req << reqFile.rdbuf(); std::ifstream expFile(expFileName); std::stringstream exp; exp << expFile.rdbuf(); expand(req.str(), exp.str()); } catch (...) { std::cerr << "ERROR processing file: " << e->d_name << std::endl; throw; } } } } //----------------------------------------------------------------------------- } // namespace metkit::mars::test int main(int argc, char** argv) { return run_tests(argc, argv); } metkit-1.16.0/tests/test_filter.cc000066400000000000000000000121371513171467200171040ustar00rootroot00000000000000/* * (C) Copyright 1996- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation * nor does it submit to any jurisdiction. */ /// @file test_filter.cc /// @date Apr 2025 /// @author Emanuele Danovaro #include #include #include #include #include #include #include "eckit/testing/Test.h" #include "eckit/types/Date.h" #include "eckit/utils/StringTools.h" #include "eckit/utils/Tokenizer.h" #include "metkit/mars/MarsParser.h" #include "metkit/mars/MarsRequest.h" #include "metkit/mars/Type.h" namespace metkit::mars::test { namespace { using ExpectedVals = std::map>; } //----------------------------------------------------------------------------- void filter(MarsRequest& r, const MarsRequest& f, const ExpectedVals& expected, const std::vector dates) { r.filter(f); for (const auto& e : expected) { if (!r.has(e.first)) { std::cerr << eckit::Colour::red << "Missing keyword: " << e.first << eckit::Colour::reset << std::endl; } EXPECT(r.has(e.first)); auto vv = r.values(e.first); if (e.first != "date") { // dates are verified at a later stage EXPECT_EQUAL(e.second.size(), vv.size()); } for (int i = 0; i < vv.size(); i++) { if (e.first == "grid") { EXPECT_EQUAL(eckit::StringTools::upper(e.second.at(i)), vv.at(i)); } else { EXPECT_EQUAL(e.second.at(i), vv.at(i)); } } } if (dates.size() > 0) { EXPECT(r.has("date")); auto dd = r.values("date"); EXPECT_EQUAL(dates.size(), dd.size()); for (int i = 0; i < dates.size(); i++) { long d = dates.at(i); if (d < 0) { eckit::Date day(d); d = day.yyyymmdd(); } EXPECT_EQUAL(std::to_string(d), dd.at(i)); } } } void filter(const std::string& text, const std::string& filter_text, const ExpectedVals& expected, std::vector dates, bool strict = true) { MarsRequest r = MarsRequest::parse(text, strict); std::string f_text = "filter," + filter_text; std::istringstream in(f_text); metkit::mars::MarsParser parser(in); std::vector f = parser.parse(); ASSERT(f.size() == 1); filter(r, f[0], expected, std::move(dates)); } void expand(const std::string& text, const std::string& filter_text, const std::string& expected, bool strict = true, std::vector dates = {}) { ExpectedVals out; eckit::Tokenizer c(","); eckit::Tokenizer e("="); eckit::Tokenizer s("/"); eckit::StringList tokens; c(expected, tokens); std::string verb; for (const auto& t : tokens) { if (verb.empty()) { verb = eckit::StringTools::lower(t); continue; } auto tt = eckit::StringTools::trim(t); eckit::StringList kv; e(tt, kv); EXPECT_EQUAL(2, kv.size()); auto key = eckit::StringTools::lower(eckit::StringTools::trim(kv[0])); if (key == "date") { EXPECT_EQUAL(0, dates.size()); } eckit::StringList vals; s(kv[1], vals); std::vector vv; for (auto v : vals) { auto val = eckit::StringTools::trim(v); if (key != "source" && key != "target") { val = eckit::StringTools::lower(val); } if (key == "date") { dates.push_back(std::stol(val)); } else { vv.push_back(val); } } if (key != "date") { out.emplace(key, vv); } } MarsRequest r = MarsRequest::parse(text, strict); std::string f_text = "filter," + filter_text; std::istringstream in(f_text); metkit::mars::MarsParser parser(in); std::vector f = parser.parse(); ASSERT(f.size() == 1); filter(r, f[0], out, std::move(dates)); } CASE("day") { const char* text = "ret,date=20250301/to/20250306"; const char* filter_text = "day=1/3/5/7/9/11/13/15/17/19/21/23/25/27/29/31"; ExpectedVals expected{{"class", {"od"}}, {"domain", {"g"}}, {"expver", {"0001"}}, {"levelist", {"1000", "850", "700", "500", "400", "300"}}, {"levtype", {"pl"}}, {"param", {"129"}}, {"step", {"0"}}, {"stream", {"oper"}}, {"time", {"1200"}}, {"type", {"an"}}}; filter(text, filter_text, expected, {20250301, 20250303, 20250305}); } //----------------------------------------------------------------------------- } // namespace metkit::mars::test int main(int argc, char** argv) { return eckit::testing::run_tests(argc, argv); } metkit-1.16.0/tests/test_gribhandle.cc000066400000000000000000000034731513171467200177210ustar00rootroot00000000000000/* * (C) Copyright 1996- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation * nor does it submit to any jurisdiction. */ /// @date Apr 2024 /// @author Christopher Bradley #include #include #include "eckit/filesystem/PathName.h" #include "eckit/io/FileHandle.h" #include "eckit/testing/Test.h" #include "eccodes.h" #include "metkit/codes/GribAccessor.h" #include "metkit/codes/GribHandle.h" namespace metkit::grib::test { //----------------------------------------------------------------------------- // Test that a gribhandle will point to the correct message in a file, given an offset. CASE("File with two messages") { // The test file has two messages of different packing types, with some junk data in between. eckit::PathName path("synthetic_2msgs.grib"); off_t* offsets; grib_context* c = nullptr; int n = 0; int err = codes_extract_offsets_malloc(c, path.asString().c_str(), PRODUCT_GRIB, &offsets, &n, 1); EXPECT(!err); EXPECT(n == 2); GribAccessor packingType("packingType"); std::vector expected = {"grid_simple", "grid_ccsds"}; eckit::FileHandle dh(path); dh.openForRead(); for (int i = 0; i < n; i++) { GribHandle h(dh, offsets[i]); EXPECT(packingType(h) == expected[i]); } free(offsets); dh.close(); } //----------------------------------------------------------------------------- } // namespace metkit::grib::test int main(int argc, char** argv) { return eckit::testing::run_tests(argc, argv); } metkit-1.16.0/tests/test_hypercube.cc000066400000000000000000000161141513171467200176040ustar00rootroot00000000000000/* * (C) Copyright 1996- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation * nor does it submit to any jurisdiction. */ /// @file test_MetFile.cc /// @date Jan 2016 /// @author Florian Rathgeber #include #include "eckit/testing/Test.h" #include "metkit/hypercube/HyperCube.h" #include "metkit/mars/MarsRequest.h" namespace metkit::mars::test { //----------------------------------------------------------------------------- CASE("test_metkit_hypercube") { const char* text = "retrieve,class=rd,type=an,stream=oper,levtype=pl,date=20191110,time=0000,step=0,expver=xxxy,domain=g,levelist=" "500,param=138"; MarsRequest r = MarsRequest::parse(text); metkit::hypercube::HyperCube cube(r); EXPECT(cube.contains(r)); EXPECT(cube.size() == 1); EXPECT(cube.vacantRequests().size() == 1); EXPECT(!(r < *cube.vacantRequests().begin())); EXPECT(!(*cube.vacantRequests().begin() < r)); } CASE("test_metkit_hypercube_subset") { const char* text = "retrieve,class=rd,type=an,stream=oper,levtype=pl,date=20191110,time=0000,step=0,expver=xxxy,domain=g,levelist=" "500/600,param=138"; MarsRequest r = MarsRequest::parse(text); metkit::hypercube::HyperCube cube(r); EXPECT(cube.size() == 2); EXPECT(cube.countVacant() == 2); EXPECT(cube.vacantRequests().size() == 1); EXPECT(!(r < *cube.vacantRequests().begin())); EXPECT(!(*cube.vacantRequests().begin() < r)); const char* text500 = "retrieve,class=rd,type=an,stream=oper,levtype=pl,date=20191110,time=0000,step=0,expver=xxxy,domain=g,levelist=" "500,param=138"; MarsRequest r500 = MarsRequest::parse(text500); const char* text600 = "retrieve,class=rd,type=an,stream=oper,levtype=pl,date=20191110,time=0000,step=0,expver=xxxy,domain=g,levelist=" "600,param=138"; MarsRequest r600 = MarsRequest::parse(text600); EXPECT_THROWS(cube.contains(r)); EXPECT(cube.contains(r500)); EXPECT(cube.contains(r600)); cube.clear(r500); EXPECT(!cube.contains(r500)); EXPECT(cube.size() == 2); EXPECT(cube.countVacant() == 1); EXPECT(cube.vacantRequests().size() == 1); EXPECT(!(r600 < *cube.vacantRequests().begin())); EXPECT(!(*cube.vacantRequests().begin() < r600)); cube.clear(r600); EXPECT(cube.countVacant() == 0); } CASE("test_metkit_hypercube_request") { const char* text = "retrieve,class=rd,type=an,stream=oper,levtype=pl,date=20191110,time=0000,step=0,expver=xxxy,domain=g,levelist=" "500/600,param=138/155"; MarsRequest r = MarsRequest::parse(text); metkit::hypercube::HyperCube cube(r); EXPECT(cube.size() == 4); EXPECT(cube.countVacant() == 4); EXPECT(cube.vacantRequests().size() == 1); EXPECT(!(r < *cube.vacantRequests().begin())); EXPECT(!(*cube.vacantRequests().begin() < r)); const char* text500 = "retrieve,class=rd,type=an,stream=oper,levtype=pl,date=20191110,time=0000,step=0,expver=xxxy,domain=g,levelist=" "500,param=138"; MarsRequest r500 = MarsRequest::parse(text500); const char* text600 = "retrieve,class=rd,type=an,stream=oper,levtype=pl,date=20191110,time=0000,step=0,expver=xxxy,domain=g,levelist=" "600,param=138"; MarsRequest r600 = MarsRequest::parse(text600); EXPECT_THROWS(cube.contains(r)); EXPECT(cube.contains(r500)); EXPECT(cube.contains(r600)); cube.clear(r500); EXPECT(!cube.contains(r500)); EXPECT(cube.size() == 4); EXPECT(cube.countVacant() == 3); EXPECT(cube.vacantRequests().size() == 2); cube.clear(r600); EXPECT(cube.countVacant() == 2); EXPECT(cube.vacantRequests().size() == 1); const char* text155 = "retrieve,class=rd,type=an,stream=oper,levtype=pl,date=20191110,time=0000,step=0,expver=xxxy,domain=g,levelist=" "500/600,param=155"; MarsRequest r155 = MarsRequest::parse(text155); EXPECT(!(r155 < *cube.vacantRequests().begin())); EXPECT(!(*cube.vacantRequests().begin() < r155)); } CASE("test_metkit_hypercube_request METK-132") { std::vector keys = {"levelist", "param"}; MarsRequest r = MarsRequest::parse("retrieve,levelist=2/4/1/3/5,param=228038/235094/235077/235078"); metkit::hypercube::HyperCube cube{r}; // unset levelist 5 for params 235077/235094 cube.clear(MarsRequest::parse("retrieve,levelist=5,param=235077")); cube.clear(MarsRequest::parse("retrieve,levelist=5,param=235094")); std::vector expected_flat_requests = { MarsRequest::parse("retrieve,levelist=1,param=228038"), MarsRequest::parse("retrieve,levelist=2,param=228038"), MarsRequest::parse("retrieve,levelist=3,param=228038"), MarsRequest::parse("retrieve,levelist=4,param=228038"), MarsRequest::parse("retrieve,levelist=5,param=228038"), MarsRequest::parse("retrieve,levelist=1,param=235077"), MarsRequest::parse("retrieve,levelist=2,param=235077"), MarsRequest::parse("retrieve,levelist=3,param=235077"), MarsRequest::parse("retrieve,levelist=4,param=235077"), MarsRequest::parse("retrieve,levelist=1,param=235094"), MarsRequest::parse("retrieve,levelist=2,param=235094"), MarsRequest::parse("retrieve,levelist=3,param=235094"), MarsRequest::parse("retrieve,levelist=4,param=235094"), MarsRequest::parse("retrieve,levelist=1,param=235078"), MarsRequest::parse("retrieve,levelist=2,param=235078"), MarsRequest::parse("retrieve,levelist=3,param=235078"), MarsRequest::parse("retrieve,levelist=4,param=235078"), MarsRequest::parse("retrieve,levelist=5,param=235078"), // These two requests we have removed from the cube: // MarsRequest::parse("retrieve,levelist=5,param=235077"), // MarsRequest::parse("retrieve,levelist=5,param=235094"), }; auto dense_requests = cube.vacantRequests(); EXPECT_EQUAL(dense_requests.size(), 2); std::vector flattened_requests; for (const auto& req : cube.vacantRequests()) { // surely this should be requests, not vacantRequests... anyway... auto flattened = req.split(keys); for (const auto& f : flattened) { flattened_requests.push_back(f); } } EXPECT_EQUAL(flattened_requests.size(), 18); EXPECT_EQUAL(flattened_requests.size(), expected_flat_requests.size()); // compare both vectors std::sort(flattened_requests.begin(), flattened_requests.end()); std::sort(expected_flat_requests.begin(), expected_flat_requests.end()); for (size_t i = 0; i < expected_flat_requests.size(); ++i) { EXPECT_EQUAL(flattened_requests[i].values("levelist"), expected_flat_requests[i].values("levelist")); EXPECT_EQUAL(flattened_requests[i].values("param"), expected_flat_requests[i].values("param")); } } } // namespace metkit::mars::test int main(int argc, char** argv) { return eckit::testing::run_tests(argc, argv); } metkit-1.16.0/tests/test_integer_range.cc000066400000000000000000000122411513171467200204240ustar00rootroot00000000000000/* * (C) Copyright 1996- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ /// @file test_integer_day.cc /// @author Metin Cakircali /// @date March 2025 #include #include #include "eckit/testing/Test.h" #include "eckit/value/Value.h" #include "metkit/mars/MarsRequest.h" #include "metkit/mars/TypeInteger.h" namespace metkit::mars::test { using ::eckit::ValueList; using ::eckit::ValueMap; //---------------------------------------------------------------------------------------------------------------------- CASE("Test TypeInteger expansion range=[1,100]") { ValueMap settings; settings["range"] = ValueList{1, 100}; TypeInteger type("day", settings); Type& tday = type; // in range for (int i = 1; i < 101; ++i) { auto num = std::to_string(i); std::string value = num; EXPECT(tday.expand(value)); EXPECT_EQUAL(value, num); } // out of range { std::string value = "0"; EXPECT(!tday.expand(value)); } { std::string value = "101"; EXPECT(!tday.expand(value)); } } //---------------------------------------------------------------------------------------------------------------------- CASE("Test TypeInteger expansion range=[1,1]") { ValueMap settings; settings["range"] = ValueList{1, 1}; TypeInteger type("day", settings); Type& tday = type; { std::string value = "1"; EXPECT(tday.expand(value)); EXPECT_EQUAL("1", value); } { std::string value = "2"; EXPECT(!tday.expand(value)); } } //---------------------------------------------------------------------------------------------------------------------- CASE("Test TypeInteger day expansion range=[-1,1]") { ValueMap settings; settings["range"] = ValueList{-1, 1}; TypeInteger type("day", settings); Type& tday = type; { std::string value = "-2"; EXPECT(!tday.expand(value)); } { std::string value = "-1"; EXPECT(tday.expand(value)); EXPECT_EQUAL("-1", value); } { std::string value = "0"; EXPECT(tday.expand(value)); EXPECT_EQUAL("0", value); } { std::string value = "1"; EXPECT(tday.expand(value)); EXPECT_EQUAL("1", value); } { std::string value = "2"; EXPECT(!tday.expand(value)); } } //---------------------------------------------------------------------------------------------------------------------- CASE("Test disseminate day expansion default by/1") { std::vector expected; for (int i = 1; i < 32; ++i) { expected.push_back(std::to_string(i)); } const auto* text = R"(disseminate, class = od, expver = 1, levtype = sfc, time = 0, stream = eefo, type = fcmean, param = sd/mn2t6/mx2t6/mtsfr/tcc/stl1/msdr/tprate/msl/rsn/2d/2t/10u/10v, step = 0-168/168-336/336-504/504-672, use = monday, day = 1/to/31, number = 0/to/10, area = 90/-180/-90/179.5, grid = .5/.5, packing = simple )"; auto request = MarsRequest::parse(text); auto days = request.values("day"); EXPECT_EQUAL(days, expected); } CASE("Test disseminate day expansion") { const auto expected = std::vector{"1", "3", "5", "7", "9", "11", "13", "15", "17", "19", "21", "23", "25", "27", "29", "31"}; const auto* text = R"(disseminate, class = od, expver = 1, levtype = sfc, time = 0, stream = eefo, type = fcmean, param = sd/mn2t6/mx2t6/mtsfr/tcc/stl1/msdr/tprate/msl/rsn/2d/2t/10u/10v, step = 0-168/168-336/336-504/504-672, use = monday, day = 1/to/31/by/2, number = 0/to/10, area = 90/-180/-90/179.5, grid = .5/.5, packing = simple )"; auto request = MarsRequest::parse(text); auto days = request.values("day"); EXPECT_EQUAL(days, expected); } CASE("Test disseminate day expansion fails outside range") { const auto* text = R"(disseminate, class = od, expver = 1, levtype = sfc, time = 0, day = 1/to/48, packing = simple )"; EXPECT_THROWS_AS(MarsRequest::parse(text), eckit::UserError); } //---------------------------------------------------------------------------------------------------------------------- } // namespace metkit::mars::test int main(int argc, char** argv) { return eckit::testing::run_tests(argc, argv); } metkit-1.16.0/tests/test_language.cc000066400000000000000000000313431513171467200174020ustar00rootroot00000000000000/* * (C) Copyright 1996- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ #include #include #include #include #include #include "eckit/exception/Exceptions.h" #include "eckit/testing/Test.h" #include "eckit/types/Date.h" #include "eckit/value/Value.h" #include "metkit/mars/MarsExpansion.h" #include "metkit/mars/MarsLanguage.h" #include "metkit/mars/MarsRequest.h" #include "metkit/mars/Type.h" #include "metkit/mars/TypeAny.h" #include "metkit/mars/TypeDate.h" #include "metkit/mars/TypeEnum.h" #include "metkit/mars/TypeExpver.h" #include "metkit/mars/TypeMixed.h" #include "metkit/mars/TypeParam.h" #include "metkit/mars/TypesFactory.h" #define EXPECT_EMPTY(request, key) EXPECT_EQUAL(request.values(key, true).size(), 0); namespace metkit::mars::test { struct Expected { const std::string verb; std::map> keyvalue; }; using Sequence = std::vector; Sequence make_random_sequence(Sequence::value_type min, Sequence::value_type max, Sequence::size_type N) { static std::mt19937 gen{std::random_device{}()}; static std::uniform_int_distribution dist(min, max); Sequence s(N); std::generate(s.begin(), s.end(), [&] { return dist(gen); }); return s; } Sequence make_power_sequence(Sequence::value_type min, Sequence::value_type max) { Sequence s; for (auto i = min; i <= max; i *= 2) { s.push_back(i); } return s; } void expect_mars(const std::string& text, const Expected& expected, bool strict = false) { auto r = MarsRequest::parse(text, strict); EXPECT_EQUAL(expected.verb, r.verb()); for (const auto& kv : expected.keyvalue) { auto v = r.values(kv.first); if (kv.first == "grid") { EXPECT(kv.second.size() == 1 && v.size() == 1 && v[0] == kv.second[0]); continue; } EXPECT_EQUAL(kv.second, kv.second); } } // ----------------------------------------------------------------------------- CASE("grid: regular Gaussian grids") { const Sequence F{16, 24, 32, 48, 64, 80, 96, 128, 160, 192, 200, 256, 320, 400, 512, 576, 640, 800, 912, 1024, 1280, 1600, 2000, 2560, 4000, 8000}; const auto Fn = [](const auto& other) { auto seq = make_random_sequence(2, 8000, 20); seq.insert(seq.end(), other.begin(), other.end()); return seq; }(F); for (const auto& n : Fn) { // known grids are expanded correctly (pattern matching doesn't work reliably here) Expected expected{"retrieve", {{"grid", {"F" + std::to_string(n)}}}}; if (std::find(F.begin(), F.end(), n) == F.end()) { expected.keyvalue.clear(); } expect_mars("ret, date=-1, grid=F" + std::to_string(n), expected); expect_mars("ret, date=-1, grid=f" + std::to_string(n), expected); expect_mars("ret, date=-1, grid=" + std::to_string(n), expected); } } // ----------------------------------------------------------------------------- CASE("grid: octahedral Gaussian grids") { for (const auto& n : make_random_sequence(2, 8000, 20 /*reduced number of tests*/)) { const Expected expected{"retrieve", {{"grid", {"O" + std::to_string(n)}}}}; expect_mars("ret, date=-1, grid=O" + std::to_string(n), expected); expect_mars("ret, date=-1, grid=o" + std::to_string(n), expected); } } // ----------------------------------------------------------------------------- CASE("grid: reduced classical Gaussian grids") { for (const auto& n : Sequence{32, 48, 64, 80, 96, 128, 160, 200, 256, 320, 400, 512, 640, 800, 1024, 1280, 8000}) { const Expected expected{"retrieve", {{"grid", {"N" + std::to_string(n)}}}}; expect_mars("ret, date=-1, grid=N" + std::to_string(n), expected); expect_mars("ret, date=-1, grid=n" + std::to_string(n), expected); } } // ----------------------------------------------------------------------------- CASE("grid: HEALPix grids") { for (const auto& n : make_power_sequence(1, 8192)) { const Expected expected{"retrieve", {{"grid", {"H" + std::to_string(n)}}}}; expect_mars("ret, date=-1, grid=H" + std::to_string(n), expected); expect_mars("ret, date=-1, grid=h" + std::to_string(n), expected); const Expected expected_ring{"retrieve", {{"grid", {"HR" + std::to_string(n)}}}}; expect_mars("ret, date=-1, grid=Hr" + std::to_string(n), expected_ring); expect_mars("ret, date=-1, grid=hR" + std::to_string(n), expected_ring); const Expected expected_nested{"retrieve", {{"grid", {"HN" + std::to_string(n)}}}}; expect_mars("ret, date=-1, grid=Hn" + std::to_string(n), expected_nested); expect_mars("ret, date=-1, grid=hN" + std::to_string(n), expected_nested); } } // ----------------------------------------------------------------------------- CASE("check language file") { EXPECT_THROWS(MarsLanguage::jsonFile("langauge.yaml")); eckit::Value file; EXPECT_NO_THROW(file = MarsLanguage::jsonFile("language.yaml")); EXPECT(file.contains("disseminate")); EXPECT(file.contains("archive")); EXPECT(file.contains("retrieve")); EXPECT(file.contains("read")); EXPECT(file.contains("get")); EXPECT(file.contains("list")); EXPECT(file.contains("compute")); EXPECT(file.contains("write")); EXPECT(file.contains("pointdb")); } CASE("check defaults and _clear_defaults") { { // check "retrieve" that _clear_defaults is not set auto request = MarsRequest::parse("retrieve,param=2t,step=10/to/12/by/1", true); EXPECT_EQUAL(request.values("class").size(), 1); EXPECT_EQUAL(request.values("class")[0], "od"); // check date is yesterday auto values = request.values("date"); EXPECT_EQUAL(values.size(), 1); std::ostringstream yesterday; yesterday << eckit::Date(-1).yyyymmdd(); EXPECT_EQUAL(values[0], yesterday.str()); } { // check "read" that _clear_defaults is set for class auto request = MarsRequest::parse("read,param=2t", true); EXPECT_EMPTY(request, "class"); EXPECT_EMPTY(request, "date"); EXPECT_EMPTY(request, "domain"); EXPECT_EMPTY(request, "expver"); EXPECT_EMPTY(request, "levelist"); EXPECT_EMPTY(request, "levtype"); EXPECT_EMPTY(request, "step"); EXPECT_EMPTY(request, "stream"); EXPECT_EMPTY(request, "time"); EXPECT_EMPTY(request, "type"); } { // check "list" that _clear_defaults is set for class auto request = MarsRequest::parse("list,param=2t", true); EXPECT_EQUAL(request.values("class").size(), 1); EXPECT_EQUAL(request.values("class")[0], "od"); EXPECT_EMPTY(request, "date"); EXPECT_EMPTY(request, "domain"); EXPECT_EMPTY(request, "expver"); EXPECT_EMPTY(request, "levelist"); EXPECT_EMPTY(request, "levtype"); EXPECT_EMPTY(request, "step"); EXPECT_EMPTY(request, "stream"); EXPECT_EMPTY(request, "time"); EXPECT_EMPTY(request, "type"); } { // check "pointdb" that _clear_defaults is set for class auto request = MarsRequest::parse("pointdb,param=2t", true); EXPECT_EMPTY(request, "class"); EXPECT_EMPTY(request, "date"); EXPECT_EMPTY(request, "domain"); EXPECT_EMPTY(request, "expver"); EXPECT_EMPTY(request, "levelist"); EXPECT_EMPTY(request, "levtype"); EXPECT_EMPTY(request, "step"); EXPECT_EMPTY(request, "stream"); EXPECT_EMPTY(request, "time"); EXPECT_EMPTY(request, "type"); } { // check "number" is not removed from the request for type=pf auto request = MarsRequest::parse("disseminate,class=od,stream=enfo,type=pf,number=2", true); EXPECT_EQUAL(request.values("number").size(), 1); EXPECT_EQUAL(request.values("number")[0], "2"); } { // check "number" is not removed from the request for type=wp auto request = MarsRequest::parse("disseminate,class=od,stream=enfo,type=wp,number=2", true); EXPECT_EQUAL(request.values("number").size(), 1); EXPECT_EQUAL(request.values("number")[0], "2"); } } CASE("check method: isData()") { EXPECT_EQUAL(MarsLanguage("retrieve").isData("class"), true); EXPECT_EQUAL(MarsLanguage("retrieve").isData("date"), true); EXPECT_EQUAL(MarsLanguage("retrieve").isData("time"), true); EXPECT_EQUAL(MarsLanguage("retrieve").isData("step"), true); EXPECT_EQUAL(MarsLanguage("retrieve").isData("number"), true); EXPECT_EQUAL(MarsLanguage("disseminate").isData("accuracy"), false); EXPECT_EQUAL(MarsLanguage("disseminate").isData("grid"), false); } CASE("check method: flatten()") { struct Output : public FlattenCallback { std::ostringstream oss; void operator()(const MarsRequest& request) override { oss << request << '\n'; } }; Output output; auto request = MarsRequest::parse( "retrieve,class=od,type=an,stream=oper,levtype=pl,time=1200,param=2t,step=10/to/14/by/2,levelist=300/400/" "500,date=20250717", true); MarsLanguage("retrieve").flatten(request, output); EXPECT_EQUAL(output.oss.str(), "retrieve,class=od,type=an,stream=oper,levtype=pl,date=20250717,time=1200,step=10,levelist=300,param=" "167,expver=0001,domain=g\n" "retrieve,class=od,type=an,stream=oper,levtype=pl,date=20250717,time=1200,step=10,levelist=400,param=" "167,expver=0001,domain=g\n" "retrieve,class=od,type=an,stream=oper,levtype=pl,date=20250717,time=1200,step=10,levelist=500,param=" "167,expver=0001,domain=g\n" "retrieve,class=od,type=an,stream=oper,levtype=pl,date=20250717,time=1200,step=12,levelist=300,param=" "167,expver=0001,domain=g\n" "retrieve,class=od,type=an,stream=oper,levtype=pl,date=20250717,time=1200,step=12,levelist=400,param=" "167,expver=0001,domain=g\n" "retrieve,class=od,type=an,stream=oper,levtype=pl,date=20250717,time=1200,step=12,levelist=500,param=" "167,expver=0001,domain=g\n" "retrieve,class=od,type=an,stream=oper,levtype=pl,date=20250717,time=1200,step=14,levelist=300,param=" "167,expver=0001,domain=g\n" "retrieve,class=od,type=an,stream=oper,levtype=pl,date=20250717,time=1200,step=14,levelist=400,param=" "167,expver=0001,domain=g\n" "retrieve,class=od,type=an,stream=oper,levtype=pl,date=20250717,time=1200,step=14,levelist=500,param=" "167,expver=0001,domain=g\n"); } CASE("check some types") { { EXPECT_THROWS(MarsLanguage("read").type("unknown")); EXPECT_THROWS(MarsLanguage("retrieve").type("unknown")); EXPECT_NO_THROW(MarsLanguage("retrieve").type("_hidden")); } { auto language = MarsLanguage("retrieve"); auto* type = language.type("class"); EXPECT(dynamic_cast(type) != nullptr); type = language.type("param"); EXPECT(dynamic_cast(type) != nullptr); type = language.type("expver"); EXPECT(dynamic_cast(type) != nullptr); type = language.type("domain"); EXPECT(dynamic_cast(type) != nullptr); type = language.type("date"); EXPECT(dynamic_cast(type) != nullptr); type = language.type("grid"); EXPECT(dynamic_cast(type) != nullptr); EXPECT_EQUAL(type->multiple(), true); type = language.type("area"); EXPECT(dynamic_cast(type) != nullptr); EXPECT_EQUAL(type->multiple(), true); type = language.type("accuracy"); EXPECT(dynamic_cast(type) != nullptr); type = language.type("resol"); EXPECT(dynamic_cast(type) != nullptr); } { auto language = MarsLanguage("archive"); auto* type = language.type("resol"); EXPECT(dynamic_cast(type) != nullptr); EXPECT_THROWS_AS(language.type("grid"), eckit::SeriousBug); EXPECT_THROWS_AS(language.type("area"), eckit::SeriousBug); } } // ----------------------------------------------------------------------------- } // namespace metkit::mars::test int main(int argc, char** argv) { return eckit::testing::run_tests(argc, argv); } metkit-1.16.0/tests/test_mars_language.cc000066400000000000000000000037761513171467200204350ustar00rootroot00000000000000 #include #include "eckit/testing/Test.h" #include "metkit/mars/MarsLanguage.h" namespace metkit::mars::test { CASE("retrieve_best_match_param_matching") { const auto language = MarsLanguage("retrieve"); // Strict is defaulted to true and this is not matching auto match = language.bestMatch("parameter", {"parameter"}, false, false, false, {}); EXPECT(match == "parameter"); }; CASE("retrieve_best_match_param_not_matching") { const auto language = MarsLanguage("retrieve"); // Strict is defaulted to true and this is not matching auto match = language.bestMatch("param", {"parameter"}, false, false, false, {}); // TODO:(TKR) THIS IS MENTAL EXPECT(match == "parameter"); auto empty = language.bestMatch("param", {"car"}, false, false, false, {}); EXPECT(empty == ""); }; CASE("retrieve_best_match_param_not_matching_throw") { const auto language = MarsLanguage("retrieve"); // Strict is defaulted to true and this is not matching auto match = language.bestMatch("param", {"parameter"}, true, false, false, {}); // TODO:(TKR) THIS IS MENTAL EXPECT(match == "parameter"); EXPECT_THROWS(language.bestMatch("param", {"car"}, true, false, false, {})); }; CASE("retrieve_best_match_param_not_matching") { const auto language = MarsLanguage("retrieve"); // Strict is defaulted to true and this is not matching auto match = language.bestMatch("param", {"parameter"}, false, false, true, {}); // TODO:(TKR) THIS IS MENTAL EXPECT(match == "parameter"); match = language.bestMatch("par", {"parameter"}, false, false, true, {}); // TODO:(TKR) THIS IS MENTAL EXPECT(match == "parameter"); match = language.bestMatch("par", {"car"}, false, false, true, {}); EXPECT(match == ""); }; } // namespace metkit::mars::test int main(int argc, char** argv) { putenv("METKIT_LANGUAGE_STRICT_MODE=0"); auto res = eckit::testing::run_tests(argc, argv); unsetenv("METKIT_LANGUAGE_STRICT_MODE"); return res; } metkit-1.16.0/tests/test_mars_language_strict.cc000066400000000000000000000014211513171467200220060ustar00rootroot00000000000000#include #include "eckit/testing/Test.h" #include "metkit/mars/MarsLanguage.h" namespace metkit::mars::test { CASE("retrieve_best_match_param_not_matching") { const auto language = MarsLanguage("retrieve"); // Strict is defaulted to true and this is not matching EXPECT_THROWS(language.bestMatch("param", {"parameter"}, false, false, true, {})); }; CASE("retrieve_best_match_param_matching") { const auto language = MarsLanguage("retrieve"); // Strict is defaulted to true and this is not matching auto match = language.bestMatch("param", {"parameter", "param"}, false, false, true, {}); EXPECT(match == "param"); }; } // namespace metkit::mars::test int main(int argc, char** argv) { return eckit::testing::run_tests(argc, argv); } metkit-1.16.0/tests/test_matcher.cc000066400000000000000000000142741513171467200172460ustar00rootroot00000000000000/* * (C) Copyright 2025- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation * nor does it submit to any jurisdiction. */ #include "eckit/testing/Test.h" #include "metkit/mars/MarsRequest.h" #include "metkit/mars/Matcher.h" using namespace eckit::testing; using namespace metkit::mars; namespace metkit::test { // ---------------------------------------------------------------------------------------------------------------------- CASE("parse string with spaces") { std::map map = parseMatchString("expver=(x[0-9a-z]{3}), number = (1|2) , stream= ^enfo$ "); EXPECT(map.size() == 3); EXPECT(map.find("expver") != map.end()); EXPECT(map.find("number") != map.end()); EXPECT(map.find("stream") != map.end()); } CASE("parse string errors") { // Check basic parsing EXPECT_THROWS_AS(parseMatchString(""), eckit::BadValue); EXPECT_THROWS_AS(parseMatchString("expver"), eckit::BadValue); EXPECT_THROWS_AS(parseMatchString("=expver"), eckit::BadValue); EXPECT_THROWS_AS(parseMatchString("expver="), eckit::BadValue); EXPECT_THROWS_AS(parseMatchString("expver,number=(1|2)"), eckit::BadValue); EXPECT_THROWS_AS(parseMatchString("number=(1|2),number=(3|4)"), eckit::BadValue); } CASE("match basic") { Matcher match_any("expver=(x[0-9a-z]{3}),number=(1|2),stream=^enfo$", Matcher::Policy::Any); Matcher match_all("expver=(x[0-9a-z]{3}),number=(1|2),stream=^enfo$", Matcher::Policy::All); MarsRequest req("retrieve"); req.setValue("expver", "xxxx"); req.values("number", {"1", "2"}); req.setValue("stream", "enfo"); req.setValue("step ", "0"); // step is not in the matcher. This should have no effect on matching EXPECT_EQUAL(req.count(), 2); EXPECT_EQUAL(match_any.match(req), true); EXPECT_EQUAL(match_all.match(req), true); } CASE("partially matching request") { Matcher match_any("expver=(x[0-9a-z]{3}),number=(1|2),stream=^enfo$", Matcher::Policy::Any); Matcher match_all("expver=(x[0-9a-z]{3}),number=(1|2),stream=^enfo$", Matcher::Policy::All); MarsRequest req("retrieve"); req.setValue("expver", "xxxx"); req.values("number", {"1", "2", "3"}); // number=3 does not match, the others do req.setValue("stream", "enfo"); EXPECT_EQUAL(req.count(), 3); EXPECT_EQUAL(match_any.match(req), true); EXPECT_EQUAL(match_all.match(req), false); } CASE("request entirely not matching") { Matcher match_any("expver=(x[0-9a-z]{3}),number=(1|2),stream=^enfo$", Matcher::Policy::Any); Matcher match_all("expver=(x[0-9a-z]{3}),number=(1|2),stream=^enfo$", Matcher::Policy::All); MarsRequest req("retrieve"); req.setValue("expver", "yyyy"); // expver=yyyy does not match req.values("number", {"1", "2"}); req.setValue("stream", "enfo"); EXPECT_EQUAL(req.count(), 2); EXPECT_EQUAL(match_any.match(req), false); EXPECT_EQUAL(match_all.match(req), false); } CASE("match with missing keys") { Matcher match_any("expver=(x[0-9a-z]{3}),number=(1|2),stream=^enfo$", Matcher::Policy::Any); Matcher match_all("expver=(x[0-9a-z]{3}),number=(1|2),stream=^enfo$", Matcher::Policy::All); MarsRequest req("retrieve"); req.setValue("expver", "xxxx"); req.values("number", {"1", "2"}); // stream is not set: matching depends on MatchMissingPolicy EXPECT_EQUAL(req.count(), 2); EXPECT_EQUAL(match_any.match(req, Matcher::DontMatchOnMissing), false); EXPECT_EQUAL(match_all.match(req, Matcher::DontMatchOnMissing), false); EXPECT_EQUAL(match_any.match(req, Matcher::MatchOnMissing), true); EXPECT_EQUAL(match_all.match(req, Matcher::MatchOnMissing), true); } CASE("match missing key and wrong values") { // -- Combinations of the above some of the above Matcher match_any("expver=(x[0-9a-z]{3}),number=(1|2),stream=^enfo$", Matcher::Policy::Any); Matcher match_all("expver=(x[0-9a-z]{3}),number=(1|2),stream=^enfo$", Matcher::Policy::All); MarsRequest req("retrieve"); req.setValue("expver", "yyyy"); // yyyy does not match req.values("number", {"1", "2", "3"}); // number=3 does not match EXPECT_EQUAL(req.count(), 3); EXPECT_EQUAL(match_any.match(req, Matcher::DontMatchOnMissing), false); EXPECT_EQUAL(match_all.match(req, Matcher::DontMatchOnMissing), false); EXPECT_EQUAL(match_any.match(req, Matcher::MatchOnMissing), false); EXPECT_EQUAL(match_all.match(req, Matcher::MatchOnMissing), false); } CASE("match missing key but some values match") { // Missing key, but expver matches, number partially matches Matcher match_any("expver=(x[0-9a-z]{3}),number=(1|2),stream=^enfo$", Matcher::Policy::Any); Matcher match_all("expver=(x[0-9a-z]{3}),number=(1|2),stream=^enfo$", Matcher::Policy::All); MarsRequest req("retrieve"); req.setValue("expver", "xxxx"); req.values("number", {"1", "2", "3"}); EXPECT_EQUAL(match_any.match(req, Matcher::DontMatchOnMissing), false); EXPECT_EQUAL(match_all.match(req, Matcher::DontMatchOnMissing), false); EXPECT_EQUAL(match_any.match(req, Matcher::MatchOnMissing), true); EXPECT_EQUAL(match_all.match(req, Matcher::MatchOnMissing), false); } CASE("match empty request") { // Testing that this does not raise an exception Matcher match_any("expver=(x[0-9a-z]{3}),number=(1|2),stream=^enfo$", Matcher::Policy::Any); Matcher match_all("expver=(x[0-9a-z]{3}),number=(1|2),stream=^enfo$", Matcher::Policy::All); MarsRequest req("retrieve"); EXPECT_EQUAL(match_any.match(req, Matcher::DontMatchOnMissing), false); EXPECT_EQUAL(match_all.match(req, Matcher::DontMatchOnMissing), false); EXPECT_EQUAL(match_any.match(req, Matcher::MatchOnMissing), true); EXPECT_EQUAL(match_all.match(req, Matcher::MatchOnMissing), true); } // ---------------------------------------------------------------------------------------------------------------------- } // namespace metkit::test int main(int argc, char** argv) { return eckit::testing::run_tests(argc, argv); } metkit-1.16.0/tests/test_multihandle.cc000066400000000000000000000035641513171467200201310ustar00rootroot00000000000000/* * (C) Copyright 1996- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation * nor does it submit to any jurisdiction. */ /// @file test_MetFile.cc /// @date Jan 2016 /// @author Florian Rathgeber #include "eckit/io/FileHandle.h" #include "eckit/io/MultiHandle.h" #include "eckit/testing/Test.h" #include "eccodes.h" namespace metkit::grib::test { //---------------------------------------------------------------------------------------------------------------------- CASE("openf filehandle") { eckit::FileHandle dh("latlon.grib"); FILE* f = dh.openf("r"); codes_handle* h; int err = 0; size_t count = 0; while ((h = codes_handle_new_from_file(nullptr, f, PRODUCT_ANY, &err))) { count++; codes_handle_delete(h); } fclose(f); EXPECT(count == 1); EXPECT(err == GRIB_SUCCESS); } //---------------------------------------------------------------------------------------------------------------------- CASE("openf multihandle") { eckit::MultiHandle dh; dh += new eckit::FileHandle("latlon.grib"); dh += new eckit::FileHandle("latlon.grib"); FILE* f = dh.openf("r"); codes_handle* h; int err = 0; size_t count = 0; while ((h = codes_handle_new_from_file(nullptr, f, PRODUCT_ANY, &err))) { count++; codes_handle_delete(h); } fclose(f); EXPECT(count == 2); EXPECT(err == GRIB_SUCCESS); } //----------------------------------------------------------------------------- } // namespace metkit::grib::test int main(int argc, char** argv) { return eckit::testing::run_tests(argc, argv); } metkit-1.16.0/tests/test_obstype.cc000066400000000000000000000043341513171467200173040ustar00rootroot00000000000000/* * (C) Copyright 1996- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ /// @file test_obstype.cc /// @author Emanuele Danovaro /// @date July 2025 #include #include #include "eckit/testing/Test.h" #include "metkit/mars/MarsLanguage.h" #include "metkit/mars/Type.h" namespace metkit::mars::test { using ::eckit::UserError; //----------------------------------------------------------------------------- void assertTypeExpansion(const std::string& name, std::vector values, const std::vector& expected) { static MarsLanguage language("retrieve"); language.type(name)->expand(values); EXPECT_EQUAL(expected, values); } CASE("Test Obstype expansions") { // times with units assertTypeExpansion("obstype", {"1"}, {"1"}); assertTypeExpansion("obstype", {"ssmi"}, {"126"}); assertTypeExpansion("obstype", {"trmm"}, {"129", "130"}); assertTypeExpansion("obstype", {"ti3r", "trmm"}, {"130", "129"}); assertTypeExpansion("obstype", {"130", "trmm"}, {"130", "129"}); assertTypeExpansion("obstype", {"trmm", "qscat"}, {"129", "130", "137", "138"}); assertTypeExpansion("obstype", {"sd"}, {"121", "122", "123", "124", "210", "212", "213", "214", "216", "217", "218", "51", "53", "54", "55", "56", "57", "59", "60", "61", "62", "63", "65", "71", "72", "73", "75", "138", "139", "153", "155", "211", "240", "250", "126", "49", "127", "129", "130", "137", "206", "207", "208", "209", "156", "154", "201", "202", "252", "245", "246"}); EXPECT_THROWS_AS(assertTypeExpansion("obstype", {"foo"}, {""}), UserError); } //----------------------------------------------------------------------------- } // namespace metkit::mars::test int main(int argc, char** argv) { return eckit::testing::run_tests(argc, argv); } metkit-1.16.0/tests/test_odbsplitter.cc000066400000000000000000000075221513171467200201540ustar00rootroot00000000000000/* * (C) Copyright 1996- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation * nor does it submit to any jurisdiction. */ #include "eckit/io/BufferList.h" #include "eckit/io/FileHandle.h" #include "eckit/message/Reader.h" #include "eckit/testing/Test.h" #include using namespace eckit::testing; namespace metkit { namespace grib { namespace test { //---------------------------------------------------------------------------------------------------------------------- class NonSeekFileHandle : public eckit::FileHandle { using eckit::FileHandle::FileHandle; bool canSeek() const override { return false; } eckit::Offset seek(const eckit::Offset&) override { NOTIMP; } }; //---------------------------------------------------------------------------------------------------------------------- CASE("read multiple matched odb frames") { // This ODB is formed of two frames with matched metadata. We should read both frames into // one message. eckit::Buffer msgdata; { NonSeekFileHandle fh("multiodb.odb"); fh.openForRead(); eckit::AutoClose closer(fh); eckit::message::Reader reader(fh); eckit::message::Message msg; msg = reader.next(); ASSERT(msg); msgdata = eckit::Buffer{msg.data(), msg.length()}; // There is only one Message in the file msg = reader.next(); EXPECT(!msg); } // And read the data in in one blob eckit::Buffer comparedata; { NonSeekFileHandle fh("multiodb.odb"); fh.openForRead(); eckit::AutoClose closer(fh); size_t expected_size = fh.size(); comparedata.resize(expected_size); EXPECT(expected_size > 0); EXPECT(fh.read(comparedata.data(), expected_size) == expected_size); } EXPECT(comparedata.size() == msgdata.size()); EXPECT(::memcmp(comparedata.data(), msgdata.data(), comparedata.size()) == 0); eckit::Log::info() << "odb size: " << msgdata.size() << std::endl; } CASE("read multiple matched odb frames") { // This ODB file is formed of four frames. Two pairs of matched metadata. This should be deconstructed into // two messages. eckit::BufferList msgdata; { eckit::FileHandle fh("multiodb2.odb"); fh.openForRead(); eckit::AutoClose closer(fh); eckit::message::Reader reader(fh); eckit::message::Message msg; for (int i = 0; i < 2; ++i) { msg = reader.next(); ASSERT(msg); msgdata.append(eckit::Buffer{msg.data(), msg.length()}); } // There is only one Message in the file msg = reader.next(); EXPECT(!msg); } // And read the data in in one blob eckit::Buffer comparedata; { eckit::FileHandle fh("multiodb2.odb"); fh.openForRead(); eckit::AutoClose closer(fh); size_t expected_size = fh.size(); comparedata.resize(expected_size); EXPECT(expected_size > 0); EXPECT(fh.read(comparedata.data(), expected_size) == expected_size); } eckit::Buffer combineddata = msgdata.consolidate(); EXPECT(comparedata.size() == combineddata.size()); EXPECT(::memcmp(comparedata.data(), combineddata.data(), combineddata.size()) == 0); eckit::Log::info() << "odb size: " << combineddata.size() << std::endl; } //---------------------------------------------------------------------------------------------------------------------- } // namespace test } // namespace grib } // namespace metkit int main(int argc, char** argv) { return run_tests(argc, argv); } metkit-1.16.0/tests/test_param_axis.cc000066400000000000000000000532471513171467200177520ustar00rootroot00000000000000/* * (C) Copyright 1996- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ /// @file test_param_axis.cc /// @author Baudouin Raoult /// @date Mai 2019 #include #include #include #include #include "eckit/testing/Test.h" #include "metkit/mars/MarsLanguage.h" #include "metkit/mars/MarsRequest.h" #include "metkit/mars/Param.h" #include "metkit/mars/ParamID.h" #include "metkit/mars/Type.h" namespace metkit::mars::test { //----------------------------------------------------------------------------- static std::ostream& operator<<(std::ostream& out, const std::vector& params) { out << '['; const char* sep = ""; for (auto p : params) { out << sep << p; sep = ", "; } out << ']'; return out; } static void test_param_axis(const std::vector& user, const std::vector& axis, const std::vector& expect, bool expectWind, bool fullTableDropping) { bool windRequested = false; MarsRequest ignore; std::vector params(user.begin(), user.end()); std::vector expected(expect.begin(), expect.end()); std::vector index(axis.begin(), axis.end()); std::sort(index.begin(), index.end()); std::cout << "Axis:" << index << std::endl; std::cout << "User:" << params << std::endl; std::cout << "Wind:" << false << std::endl; ParamID::normalise(ignore, params, index, windRequested, fullTableDropping); std::cout << "Expected Params:" << expected << std::endl; std::cout << "Returned Params:" << params << std::endl; std::cout << "Expected Wind:" << expectWind << std::endl; std::cout << "Returned Wind:" << windRequested << std::endl; EXPECT_EQUAL(expectWind, windRequested); EXPECT_EQUAL(params, expected); } static void test_param_axis(const std::vector& user, const std::vector& axis, const std::vector& expect, bool expectWind) { bool windRequested = false; MarsRequest ignore; std::vector params(user.begin(), user.end()); std::vector expected(expect.begin(), expect.end()); std::vector index(axis.begin(), axis.end()); std::sort(index.begin(), index.end()); std::cout << "Axis:" << index << std::endl; std::cout << "User:" << params << std::endl; std::cout << "Wind:" << false << std::endl; ParamID::normalise(ignore, params, index, windRequested); std::cout << "Expected Params:" << expected << std::endl; std::cout << "Returned Params:" << params << std::endl; std::cout << "Expected Wind:" << expectWind << std::endl; std::cout << "Returned Wind:" << windRequested << std::endl; EXPECT_EQUAL(expectWind, windRequested); EXPECT_EQUAL(params, expected); } void assertTypeExpansion(const std::string& name, std::vector values, const std::vector& expected) { static MarsLanguage language("retrieve"); MarsRequest req; req.setValuesTyped(language.type(name), values); req = language.expand(req, false, true); EXPECT_EQUAL(expected, req.values(name)); } CASE("canonical param") { assertTypeExpansion("param", {"129.228"}, {"228129"}); assertTypeExpansion("param", {"228129"}, {"228129"}); EXPECT_THROWS_AS(assertTypeExpansion("param", {".228"}, {""}), eckit::UserError); EXPECT_THROWS_AS(assertTypeExpansion("param", {"9999"}, {""}), eckit::UserError); assertTypeExpansion("param", {"254"}, {"254"}); assertTypeExpansion("param", {"254.128"}, {"254"}); assertTypeExpansion("param", {"254.129"}, {"129254"}); assertTypeExpansion("param", {"3003"}, {"3003"}); assertTypeExpansion("param", {"999.128"}, {"999"}); EXPECT_THROWS_AS(assertTypeExpansion("param", {"999.129"}, {"129999"}), eckit::UserError); EXPECT_THROWS_AS(assertTypeExpansion("param", {"1000.128"}, {""}), eckit::UserError); EXPECT_THROWS_AS(assertTypeExpansion("param", {"228003.228"}, {""}), eckit::UserError); } CASE("trivial") { std::vector user = {"1", "2", "3"}; std::vector axis = {"1", "2", "3"}; std::vector expect = {"1", "2", "3"}; test_param_axis(user, axis, expect, false); } CASE("wind1") { std::vector user = {"131", "132"}; std::vector axis = {"138", "155"}; std::vector expect = {"131", "132", "138", "155"}; test_param_axis(user, axis, expect, true); } CASE("wind2") { std::vector user = {"131", "132"}; std::vector axis = {"131", "132", "138", "155"}; std::vector expect = {"131", "132"}; test_param_axis(user, axis, expect, false); } CASE("wind3") { std::vector user = {"131", "132", "138", "155"}; std::vector axis = {"138", "155"}; std::vector expect = {"131", "132", "138", "155"}; test_param_axis(user, axis, expect, true); } CASE("wind4") { std::vector user = {"131.128", "132.128", "138.128", "155.128"}; std::vector axis = {"138.128", "155.128"}; std::vector expect = {"131.128", "132.128", "138.128", "155.128"}; test_param_axis(user, axis, expect, true); } CASE("wind5") { std::vector user = { "131.128", "132.128", }; std::vector axis = {"138", "155"}; std::vector expect = {"131", "132", "138", "155"}; test_param_axis(user, axis, expect, true); } CASE("wind6") { std::vector user = {"131.128", "132.128", "138.128", "155.128"}; std::vector axis = {"138", "155"}; std::vector expect = {"131", "132", "138", "155"}; test_param_axis(user, axis, expect, true); } CASE("wind7") { std::vector user = {"131", "132", "138", "155"}; std::vector axis = {"138.128", "155.128"}; std::vector expect = {"131.128", "132.128", "138.128", "155.128"}; test_param_axis(user, axis, expect, true); } CASE("wind8") { std::vector user = { "131", "132", }; std::vector axis = {"138.128", "155.128"}; std::vector expect = {"131.128", "132.128", "138.128", "155.128"}; test_param_axis(user, axis, expect, true); } CASE("wind9") { std::vector user = { "131", "132", }; std::vector axis = {"138", "155", "210131"}; std::vector expect = {"131", "132", "138", "155"}; test_param_axis(user, axis, expect, true); } CASE("wind10") { std::vector user = { "131", "132", }; std::vector axis = {"129138", "129155"}; std::vector expect = {"129131", "129132", "129138", "129155"}; test_param_axis(user, axis, expect, true); } CASE("wind11") { std::vector user = { "131", "132", }; std::vector axis = {"138", "155", "129138", "129155"}; std::vector expect = {"131", "132", "138", "155"}; test_param_axis(user, axis, expect, true); } CASE("wind12") { std::vector user = { "131", "132.129", }; std::vector axis = {"138", "155", "129138", "129155"}; std::vector expect = {"131", "129132", "138", "155", "129138", "129155"}; test_param_axis(user, axis, expect, true); } CASE("wind13") { std::vector user = { "131.128", "132.128", }; std::vector axis = {"138", "155", "210131"}; std::vector expect = {"131", "132", "138", "155"}; test_param_axis(user, axis, expect, true); } CASE("wind14") { std::vector user = { "131", }; std::vector axis = {"138", "155", "210131"}; std::vector expect = {"131", "138", "155"}; test_param_axis(user, axis, expect, true); } CASE("wind15") { std::vector user = { "210131", }; std::vector axis = {"138", "155", "210131"}; std::vector expect = {"210131"}; test_param_axis(user, axis, expect, false); } CASE("wind16") { std::vector user = { "210131", "131", }; std::vector axis = {"138", "155", "210131"}; std::vector expect = {"210131", "131", "138", "155"}; test_param_axis(user, axis, expect, true); } CASE("wind17") { std::vector user = { "210131", "132", }; std::vector axis = {"138", "155", "210131"}; std::vector expect = {"210131", "132", "138", "155"}; test_param_axis(user, axis, expect, true); } CASE("wind18") { std::vector user = { "210131", "131.128", }; std::vector axis = {"138", "155", "210131"}; std::vector expect = {"210131", "131", "138", "155"}; test_param_axis(user, axis, expect, true); } CASE("wind19") { std::vector user = { "132", }; std::vector axis = {"160138", "160155", "160131"}; std::vector expect = {"160132", "160138", "160155"}; test_param_axis(user, axis, expect, true); } CASE("wind20") { std::vector user = { "131", }; std::vector axis = {"160138", "160155", "160131"}; std::vector expect = {"160131"}; test_param_axis(user, axis, expect, false); } CASE("wind21") { std::vector user = { "132", }; std::vector axis = { "120138", "120155", "170138", "170155", }; std::vector expect = {"170132", "170138", "170155"}; test_param_axis(user, axis, expect, true); } CASE("mixed") { std::vector user = { "129", }; std::vector axis = {"129.128", "129"}; std::vector expect = {"129"}; test_param_axis(user, axis, expect, false); } CASE("ocean1") { std::vector user = {"145"}; std::vector axis = {"145.128", "164.128", "175.128", "148.128", "145.151", "164.151", "175.151", "148.151"}; std::vector expect = {"145.128"}; test_param_axis(user, axis, expect, false); } CASE("ocean2") { std::vector user = {"145", "151145"}; std::vector axis = {"145.128", "164.128", "175.128", "148.128", "145.151", "164.151", "175.151", "148.151"}; std::vector expect = {"145.128", "145.151"}; test_param_axis(user, axis, expect, false); } CASE("ocean3") { std::vector user = {"145", "164", "175", "148", "151145"}; std::vector axis = {"145.128", "164.128", "175.128", "148.128", "145.151", "164.151", "175.151", "148.151"}; std::vector expect = {"145.128", "164.128", "175.128", "148.128", "145.151"}; test_param_axis(user, axis, expect, false); } CASE("ocean4") { std::vector user = {"145", "164", "175", "148"}; std::vector axis = {"145.151", "164.151", "175.151", "148.151"}; std::vector expect = {"145.151", "164.151", "175.151", "148.151"}; test_param_axis(user, axis, expect, false); } CASE("MARS-794 - GRIB1 and GRIB2 in axis") { // Note the paramId's at the end std::vector axis = { "1.228", "3.228", "7.228", "8.128", "8.228", "9.128", "9.228", "10.228", "11.228", "12.228", "13.228", "14.228", "20.3", "20.128", "21.228", "22.228", "23.228", "24.228", "26.128", "29.228", "31.128", "32.128", "33.128", "34.128", "35.128", "36.128", "37.128", "38.128", "39.128", "40.128", "41.128", "42.128", "44.128", "44.228", "45.128", "46.228", "47.128", "47.228", "48.228", "49.128", "50.128", "57.128", "58.128", "59.128", "66.128", "67.128", "78.128", "79.128", "80.228", "81.228", "82.228", "83.228", "84.228", "85.228", "88.228", "89.228", "90.228", "98.174", "129.128", "130.151", "131.151", "131.228", "132.151", "132.228", "134.128", "136.128", "137.128", "139.128", "141.128", "142.128", "143.128", "144.128", "145.128", "145.151", "146.128", "147.128", "148.128", "148.151", "151.128", "159.128", "163.151", "164.128", "164.151", "165.128", "166.128", "167.128", "168.128", "169.128", "170.128", "172.128", "175.128", "175.151", "176.128", "177.128", "178.128", "179.128", "180.128", "181.128", "182.128", "183.128", "186.128", "187.128", "188.128", "189.128", "195.128", "196.128", "197.128", "198.128", "201.128", "202.128", "205.128", "206.128", "208.128", "209.128", "210.128", "211.128", "212.128", "213.128", "216.228", "217.228", "218.228", "219.228", "220.228", "221.228", "226.228", "227.228", "228.128", "229.128", "230.128", "231.128", "232.128", "235.128", "236.128", "238.128", "239.228", "240.228", "241.228", "243.128", "244.128", "245.128", "246.228", "247.228", "251.228", "162071", "162072", "228050", "228051", "260015", "260048", "260109", "260121", "260123", "26.228", "27.228", "28.228", "121.128", "122.128", "123.128", "222.228", "223.228", "224.228", "225.228", "228035", "228036", "228057", "228058"}; // by parameter xxx SECTION("by xxx only - priority to table 128") { std::vector user = {"148", "145", "164", "175"}; std::vector expect = {"148.128", "145.128", "164.128", "175.128"}; test_param_axis(user, axis, expect, false); } SECTION("by xxx and param.table") { std::vector user = {"148", "145.128", "164", "175.151"}; std::vector expect = {"148.128", "145.128", "164.128", "175.151"}; test_param_axis(user, axis, expect, false); } SECTION("by xxx and paramId") { std::vector user = {"148", "128145", "164", "151175"}; std::vector expect = {"148.128", "145.128", "164.128", "175.151"}; test_param_axis(user, axis, expect, false); } SECTION("by xxx and paramId and param.table") { std::vector user = {"148", "128145", "164", "175.151"}; std::vector expect = {"148.128", "145.128", "164.128", "175.151"}; test_param_axis(user, axis, expect, false); } SECTION("by xxx and paramId all ") { std::vector user = {"148", "145", "164", "175", "151148", "151145", "151164", "151175"}; std::vector expect = {"148.128", "145.128", "164.128", "175.128", "148.151", "145.151", "164.151", "175.151"}; test_param_axis(user, axis, expect, false); } // by paramId SECTION("by paramId only 128") { std::vector user = {"128148", "128145", "128164", "128175"}; std::vector expect = {"148.128", "145.128", "164.128", "175.128"}; test_param_axis(user, axis, expect, false); } SECTION("by paramId only 151") { std::vector user = {"151148", "151145", "151164", "151175"}; std::vector expect = {"148.151", "145.151", "164.151", "175.151"}; test_param_axis(user, axis, expect, false); } SECTION("by paramId mixed 128 and 151") { std::vector user = {"151148", "128145", "128164", "151175"}; std::vector expect = {"148.151", "145.128", "164.128", "175.151"}; test_param_axis(user, axis, expect, false); } SECTION("by paramId all") { std::vector user = {"151148", "151145", "151164", "151175", "128148", "128145", "128164", "128175"}; std::vector expect = {"148.151", "145.151", "164.151", "175.151", "148.128", "145.128", "164.128", "175.128"}; test_param_axis(user, axis, expect, false); } // by param.table SECTION("by param.table only 128") { std::vector user = {"148.128", "145.128", "164.128", "175.128"}; std::vector expect = {"148.128", "145.128", "164.128", "175.128"}; test_param_axis(user, axis, expect, false); } SECTION("by param.table only 151") { std::vector user = {"148.151", "145.151", "164.151", "175.151"}; std::vector expect = {"148.151", "145.151", "164.151", "175.151"}; test_param_axis(user, axis, expect, false); } SECTION("by param.table mixed 128 and 151") { std::vector user = {"148.128", "145.151", "164.128", "175.151"}; std::vector expect = {"148.128", "145.151", "164.128", "175.151"}; test_param_axis(user, axis, expect, false); } SECTION("by param.table all") { std::vector user = {"148.151", "145.151", "164.151", "175.151", "148.128", "145.128", "164.128", "175.128"}; std::vector expect = {"148.151", "145.151", "164.151", "175.151", "148.128", "145.128", "164.128", "175.128"}; test_param_axis(user, axis, expect, false); } } CASE("table1") { std::vector user = {"129", "130.128"}; std::vector axis = {"129.128", "130"}; std::vector expect = {"129.128", "130"}; test_param_axis(user, axis, expect, false); } CASE("table2") { std::vector user = {"129", "130.128"}; std::vector axis = {"129.128", "130"}; std::vector expect = {"129.128", "130"}; test_param_axis(user, axis, expect, false); } CASE("table3") { std::vector user = { "129", }; std::vector axis = { "140129", }; std::vector expect = {"140129"}; test_param_axis(user, axis, expect, false); } CASE("table4") { std::vector user = { "129", }; std::vector axis = { "129.140", }; std::vector expect = {"129.140"}; test_param_axis(user, axis, expect, false); } CASE("table5") { std::vector user = { "129", }; std::vector axis = {"129.128", "129.140"}; std::vector expect = {"129.128"}; test_param_axis(user, axis, expect, false); } CASE("table6") { std::vector user = { "129.128", }; std::vector axis = {"129.128", "129.140"}; std::vector expect = {"129.128"}; test_param_axis(user, axis, expect, false); } CASE("table7") { std::vector user = { "129", }; std::vector axis = {"129", "140129"}; std::vector expect = {"129"}; test_param_axis(user, axis, expect, false); } CASE("table8") { std::vector user = { "129.128", }; std::vector axis = {"129", "140129"}; std::vector expect = {"129"}; test_param_axis(user, axis, expect, false); } CASE("table9") { std::vector user = { "129.128", }; std::vector axis = {"129", "140129"}; std::vector expect = {"129"}; test_param_axis(user, axis, expect, false); } CASE("table10") { std::vector user = {"131"}; std::vector axis = {"210131"}; std::vector expect = {}; test_param_axis(user, axis, expect, false, false); test_param_axis(user, axis, axis, false, true); } CASE("table11") { std::vector user = {"131"}; std::vector axis = {"131.210"}; std::vector expect = {}; test_param_axis(user, axis, expect, false, false); test_param_axis(user, axis, axis, false, true); } CASE("table12") { std::vector user = {"131", "132"}; std::vector axis = {"210131", "170131", "180131", "160132"}; std::vector expect = {"170131", "160132"}; test_param_axis(user, axis, expect, false); } CASE("table13") { std::vector user = {"131", "132"}; std::vector axis = {"210131", "131.170", "180131", "160132"}; std::vector expect = {"131.170", "160132"}; test_param_axis(user, axis, expect, false); } CASE("table14") { std::vector user = {"134", "133"}; std::vector axis = {"210131", "133.170", "180134"}; std::vector expect = {"180134", "133.170"}; test_param_axis(user, axis, expect, false); } CASE("table15") { std::vector user = {"134", "133.128"}; std::vector axis = {"210131", "133.170", "180134"}; std::vector expect = {"180134"}; test_param_axis(user, axis, expect, false); } } // namespace metkit::mars::test //----------------------------------------------------------------------------- int main(int argc, char** argv) { return eckit::testing::run_tests(argc, argv); } metkit-1.16.0/tests/test_request.cc000066400000000000000000000113371513171467200173100ustar00rootroot00000000000000/* * (C) Copyright 1996- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation * nor does it submit to any jurisdiction. */ /// @file test_request.cc /// @date Jul 2024 /// @author Emanuele Danovaro #include "eckit/log/JSON.h" #include "eckit/types/Date.h" #include "metkit/mars/MarsExpansion.h" #include "metkit/mars/MarsLanguage.h" #include "metkit/mars/MarsParser.h" #include "metkit/mars/MarsRequest.h" #include "metkit/mars/Type.h" #include "eckit/testing/Test.h" #include "eckit/utils/Tokenizer.h" using namespace eckit::testing; namespace metkit { namespace mars { namespace test { //----------------------------------------------------------------------------- CASE("test_request_json") { { const char* text = "retrieve,class=od,expver=0079,stream=enfh,date=20240729,time=00/" "12,type=fcmean,levtype=sfc,step=24,number=1/to/2,param=mucin/mucape/tprate"; MarsRequest r = MarsRequest::parse(text); { std::stringstream ss; eckit::JSON plain(ss); r.json(plain); EXPECT_EQUAL( ss.str(), "{\"class\":\"od\",\"type\":\"fcmean\",\"stream\":\"enfh\",\"levtype\":\"sfc\",\"date\":\"20240729\"," "\"time\":[\"0000\",\"1200\"],\"step\":\"24\",\"expver\":\"0079\",\"number\":[\"1\",\"2\"],\"param\":[" "\"228236\",\"228235\",\"172228\"],\"domain\":\"g\"}"); } { std::stringstream ss; eckit::JSON array(ss); r.json(array, true); EXPECT_EQUAL( ss.str(), "{\"class\":\"od\",\"type\":\"fcmean\",\"stream\":\"enfh\",\"levtype\":\"sfc\",\"date\":[\"20240729\"]," "\"time\":[\"0000\",\"1200\"],\"step\":[\"24\"],\"expver\":\"0079\",\"number\":[\"1\",\"2\"],\"param\":" "[\"228236\",\"228235\",\"172228\"],\"domain\":\"g\"}"); } } { const char* text = "retrieve,class=od,expver=1,stream=wave,date=20240729,time=00,type=an,levtype=sfc,step=24,param=2dfd "; MarsRequest r = MarsRequest::parse(text); { std::stringstream ss; eckit::JSON plain(ss); r.json(plain); EXPECT_EQUAL(ss.str(), "{\"class\":\"od\",\"type\":\"an\",\"stream\":\"wave\",\"levtype\":\"sfc\",\"date\":" "\"20240729\",\"time\":\"0000\",\"step\":\"24\",\"expver\":\"0001\",\"param\":\"140251\"," "\"domain\":\"g\"}"); } { std::stringstream ss; eckit::JSON array(ss); r.json(array, true); EXPECT_EQUAL(ss.str(), "{\"class\":\"od\",\"type\":\"an\",\"stream\":\"wave\",\"levtype\":\"sfc\",\"date\":[" "\"20240729\"],\"time\":[\"0000\"],\"step\":[\"24\"],\"expver\":\"0001\",\"param\":[" "\"140251\"],\"domain\":\"g\"}"); } } } CASE("test_request_count") { { const char* text = "retrieve,class=od,expver=0079,stream=enfh,date=20240729,time=00/" "12,type=fcmean,levtype=sfc,step=24,number=1/to/2,param=mucin/mucape/tprate"; MarsRequest r = MarsRequest::parse(text); EXPECT_EQUAL(12, r.count()); } { const char* text = "retrieve,accuracy=16,class=od,date=20230810,expver=1,levelist=1/to/" "137,levtype=ml,number=-1,param=z,process=local,step=000,stream=scda,time=18,type=an,target=reference.data"; MarsRequest r = MarsRequest::parse(text); EXPECT_EQUAL(1, r.count()); } { const char* text = "retrieve,accuracy=16,class=od,date=20230810,expver=1,levelist=1/to/137,levtype=ml,number=-1,param=z/" "t,process=local,step=000,stream=scda,time=18,type=an,target=reference.data"; MarsRequest r = MarsRequest::parse(text); EXPECT_EQUAL(138, r.count()); } { const char* text = "retrieve,accuracy=16,class=od,date=20230810,expver=1,levelist=1/to/137,levtype=ml,number=-1,param=22/127/" "128/129/152/u/v,process=local,step=000,stream=scda,time=18,type=an,target=reference.data"; MarsRequest r = MarsRequest::parse(text); EXPECT_EQUAL(279, r.count()); } } //----------------------------------------------------------------------------- } // namespace test } // namespace mars } // namespace metkit int main(int argc, char** argv) { return run_tests(argc, argv); } metkit-1.16.0/tests/test_step.cc000066400000000000000000000070531513171467200165730ustar00rootroot00000000000000/* * (C) Copyright 1996- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ /// @file test_step.cc /// @author Emanuele Danovaro /// @date March 2025 #include #include #include "eckit/testing/Test.h" #include "metkit/mars/MarsLanguage.h" #include "metkit/mars/Type.h" namespace metkit::mars::test { using ::eckit::BadValue; //----------------------------------------------------------------------------- void assertTypeExpansion(const std::string& name, std::vector values, const std::vector& expected) { static MarsLanguage language("retrieve"); language.type(name)->expand(values); EXPECT_EQUAL(expected, values); } CASE("Test Step expansions") { // times with units assertTypeExpansion("step", {"0"}, {"0"}); assertTypeExpansion("step", {"12"}, {"12"}); assertTypeExpansion("step", {"260m"}, {"4h20m"}); assertTypeExpansion("step", {"30m", "1h", "1h30m", "120m"}, {"30m", "1", "1h30m", "2"}); assertTypeExpansion("step", {"0-1"}, {"0-1"}); assertTypeExpansion("step", {"30m-60m"}, {"30m-1"}); EXPECT_THROWS_AS(assertTypeExpansion("step", {"-1"}, {""}), BadValue); EXPECT_THROWS_AS(assertTypeExpansion("step", {"2-1"}, {""}), BadValue); assertTypeExpansion("step", {"0-3", "to", "9-12", "by", "3h"}, {"0-3", "3-6", "6-9", "9-12"}); assertTypeExpansion("step", {"0-3", "to", "0-12", "by", "3"}, {"0-3"}); assertTypeExpansion("step", {"0-30m", "to", "1h30m-2h", "by", "30m"}, {"0-30m", "30m-1", "1-1h30m", "1h30m-2"}); assertTypeExpansion( "step", {"0m", "to", "1440m", "by", "10m"}, {"0", "10m", "20m", "30m", "40m", "50m", "1", "1h10m", "1h20m", "1h30m", "1h40m", "1h50m", "2", "2h10m", "2h20m", "2h30m", "2h40m", "2h50m", "3", "3h10m", "3h20m", "3h30m", "3h40m", "3h50m", "4", "4h10m", "4h20m", "4h30m", "4h40m", "4h50m", "5", "5h10m", "5h20m", "5h30m", "5h40m", "5h50m", "6", "6h10m", "6h20m", "6h30m", "6h40m", "6h50m", "7", "7h10m", "7h20m", "7h30m", "7h40m", "7h50m", "8", "8h10m", "8h20m", "8h30m", "8h40m", "8h50m", "9", "9h10m", "9h20m", "9h30m", "9h40m", "9h50m", "10", "10h10m", "10h20m", "10h30m", "10h40m", "10h50m", "11", "11h10m", "11h20m", "11h30m", "11h40m", "11h50m", "12", "12h10m", "12h20m", "12h30m", "12h40m", "12h50m", "13", "13h10m", "13h20m", "13h30m", "13h40m", "13h50m", "14", "14h10m", "14h20m", "14h30m", "14h40m", "14h50m", "15", "15h10m", "15h20m", "15h30m", "15h40m", "15h50m", "16", "16h10m", "16h20m", "16h30m", "16h40m", "16h50m", "17", "17h10m", "17h20m", "17h30m", "17h40m", "17h50m", "18", "18h10m", "18h20m", "18h30m", "18h40m", "18h50m", "19", "19h10m", "19h20m", "19h30m", "19h40m", "19h50m", "20", "20h10m", "20h20m", "20h30m", "20h40m", "20h50m", "21", "21h10m", "21h20m", "21h30m", "21h40m", "21h50m", "22", "22h10m", "22h20m", "22h30m", "22h40m", "22h50m", "23", "23h10m", "23h20m", "23h30m", "23h40m", "23h50m", "24"}); } //----------------------------------------------------------------------------- } // namespace metkit::mars::test int main(int argc, char** argv) { return eckit::testing::run_tests(argc, argv); } metkit-1.16.0/tests/test_steprange_axis.cc000066400000000000000000000116011513171467200206260ustar00rootroot00000000000000/* * (C) Copyright 1996- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ /// @file test_param_axis.cc /// @author Baudouin Raoult /// @date Mai 2019 #include #include #include #include #include "eckit/testing/Test.h" #include "eckit/types/FloatCompare.h" #include "metkit/mars/StepRange.h" #include "metkit/mars/StepRangeNormalise.h" namespace eckit { template <> struct VectorPrintSelector { using selector = VectorPrintSimple; }; } // namespace eckit namespace metkit::mars::test { //----------------------------------------------------------------------------- CASE("steprange") { { StepRange sr{0, 24}; EXPECT_EQUAL(sr.from(), 0); EXPECT_EQUAL(sr.to(), 24); } { StepRange sr{"0-24"}; EXPECT_EQUAL(sr.from(), 0); EXPECT_EQUAL(sr.to(), 24); } { StepRange sr{0, .5}; EXPECT_EQUAL(sr.from(), 0); EXPECT(eckit::types::is_approximately_equal(sr.to(), 0.5)); } { StepRange sr{"0-30m"}; EXPECT_EQUAL(sr.from(), 0); EXPECT(eckit::types::is_approximately_equal(sr.to(), 0.5)); } { StepRange sr{"0-24s"}; EXPECT_EQUAL(sr.from(), 0); EXPECT(eckit::types::is_approximately_equal(sr.to(), 24. / 3600.)); } { StepRange sr{"40m-260m"}; EXPECT(eckit::types::is_approximately_equal(sr.from(), 2. / 3.)); EXPECT(eckit::types::is_approximately_equal(sr.to(), 4 + 1. / 3.)); } { StepRange sr{"20m"}; EXPECT_EQUAL(sr.toString(), "20m"); EXPECT_EQUAL(sr.toString(true), "20m"); } { StepRange sr{"60m"}; EXPECT_EQUAL(sr.toString(), "1"); EXPECT_EQUAL(sr.toString(true, false), "1"); EXPECT_EQUAL(sr.toString(true, true), "1h"); } { StepRange sr{"1d"}; EXPECT_EQUAL(sr.toString(), "24"); EXPECT_EQUAL(sr.toString(true, false), "1d"); EXPECT_EQUAL(sr.toString(true, true), "1d"); } { StepRange sr{"25"}; EXPECT_EQUAL(sr.toString(), "25"); EXPECT_EQUAL(sr.toString(true, false), "1d1h"); EXPECT_EQUAL(sr.toString(true, true), "1d1h"); } } static void test_steprange_axis(const std::vector& user, const std::vector& axis, const std::vector& expect) { std::vector values(user.begin(), user.end()); std::vector result(expect.begin(), expect.end()); std::vector index(axis.begin(), axis.end()); std::sort(index.begin(), index.end()); std::cout << "User:" << values << std::endl; std::cout << "Axis:" << index << std::endl; StepRangeNormalise::normalise(values, index); std::cout << "Result:" << values << std::endl; EXPECT(values == result); } CASE("trivial") { std::vector user = {"1", "2", "3"}; std::vector axis = {"1", "2", "3"}; std::vector expect = {"1", "2", "3"}; test_steprange_axis(user, axis, expect); } CASE("subselection") { std::vector user = {"2", "3"}; std::vector axis = {"1", "2", "3"}; std::vector expect = {"2", "3"}; test_steprange_axis(user, axis, expect); } CASE("missing values") { std::vector user = {"1", "2", "3"}; std::vector axis = {"1", "3"}; std::vector expect = {"1", "3"}; test_steprange_axis(user, axis, expect); } CASE("ranges") { std::vector user = {"0-24", "24-48", "3-9"}; std::vector axis = {"0-24", "6-30", "12-36", "18-42", "24-48"}; std::vector expect = {"0-24", "24-48"}; test_steprange_axis(user, axis, expect); } CASE("default start-point") { std::vector user = {"1", "2", "24", "25"}; std::vector axis = {"1", "0-1", "3", "0-3", "0-24", "25"}; std::vector expect = {"1", "0-1", "0-24", "25"}; test_steprange_axis(user, axis, expect); } CASE("match range start") { // SDS: I'm not really sure why this is supported, but the original // MARS code did it... std::vector user = {"2-24"}; std::vector axis = {"1", "2", "3"}; std::vector expect = {"2"}; test_steprange_axis(user, axis, expect); } } // namespace metkit::mars::test //----------------------------------------------------------------------------- int main(int argc, char** argv) { return eckit::testing::run_tests(argc, argv); } metkit-1.16.0/tests/test_time.cc000066400000000000000000000105121513171467200165500ustar00rootroot00000000000000/* * (C) Copyright 1996- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ /// @file test_time.cc /// @author Simon Smart /// @author Emanuele Danovaro /// @date April 2020 #include #include #include "eckit/testing/Test.h" #include "metkit/mars/MarsLanguage.h" #include "metkit/mars/Type.h" #include "metkit/mars/TypeTime.h" namespace metkit::mars::test { using ::eckit::BadTime; using ::eckit::BadValue; using ::eckit::Value; //----------------------------------------------------------------------------- void assertTypeExpansion(const std::string& name, std::vector values, const std::vector& expected) { static MarsLanguage language("retrieve"); language.type(name)->expand(values); EXPECT_EQUAL(values.size(), expected.size()); EXPECT_EQUAL(expected, values); } void checkExpansion(const Type& tt, const std::string& value, const std::string& expected) { auto expanded = tt.tidy(value); EXPECT_EQUAL(expected, expanded); } CASE("Test TypeTime expansions") { TypeTime ttime("time", Value()); Type& tt(ttime); // 1 and 2-digit times checkExpansion(tt, "0", "0000"); checkExpansion(tt, "00", "0000"); checkExpansion(tt, "12", "1200"); checkExpansion(tt, "6", "0600"); checkExpansion(tt, "06", "0600"); // 3 and 4-digit times checkExpansion(tt, "000", "0000"); checkExpansion(tt, "0000", "0000"); checkExpansion(tt, "012", "0012"); checkExpansion(tt, "0012", "0012"); checkExpansion(tt, "1234", "1234"); checkExpansion(tt, "623", "0623"); checkExpansion(tt, "0623", "0623"); { EXPECT_THROWS_AS(auto vv = tt.tidy("675"), BadTime); } // 5 and 6-digit times checkExpansion(tt, "00000", "0000"); checkExpansion(tt, "001200", "0012"); checkExpansion(tt, "123400", "1234"); checkExpansion(tt, "062300", "0623"); checkExpansion(tt, "62300", "0623"); { // We don't support seconds yet. EXPECT_THROWS_AS(auto vv = tt.tidy("000012"), BadValue); } { // We don't support seconds yet. EXPECT_THROWS_AS(auto vv = tt.tidy("123456"), BadValue); } { // We don't support time > 24h EXPECT_THROWS_AS(auto vv = tt.tidy("283456"), BadValue); } // times with colons checkExpansion(tt, "0:0", "0000"); checkExpansion(tt, "00:00", "0000"); checkExpansion(tt, "00:00:00", "0000"); checkExpansion(tt, "0:12", "0012"); checkExpansion(tt, "00:12", "0012"); checkExpansion(tt, "12:34", "1234"); checkExpansion(tt, "6:23", "0623"); checkExpansion(tt, "06:23", "0623"); checkExpansion(tt, "00:12:00", "0012"); checkExpansion(tt, "12:34:00", "1234"); checkExpansion(tt, "06:23:00", "0623"); checkExpansion(tt, "6:23:00", "0623"); { EXPECT_THROWS_AS(auto vv = tt.tidy("00:62"), BadTime); } { // We don't support seconds yet. EXPECT_THROWS_AS(auto vv = tt.tidy("00:00:12"), BadValue); } { // We don't support seconds yet. EXPECT_THROWS_AS(auto vv = tt.tidy("12:34:56"), BadValue); } // times with units assertTypeExpansion("time", {"0h"}, {"0000"}); assertTypeExpansion("time", {"00H"}, {"0000"}); assertTypeExpansion("time", {"60m"}, {"0100"}); assertTypeExpansion("time", {"2h30m"}, {"0230"}); assertTypeExpansion("time", {"60s"}, {"0001"}); EXPECT_THROWS_AS(assertTypeExpansion("time", {"6s"}, {"0000"}), BadValue); EXPECT_THROWS_AS(assertTypeExpansion("time", {"25"}, {"0000"}), BadValue); // from to by assertTypeExpansion("time", {"0", "to", "18"}, {"0000", "0600", "1200", "1800"}); assertTypeExpansion("time", {"0", "to", "6", "by", "1"}, {"0000", "0100", "0200", "0300", "0400", "0500", "0600"}); assertTypeExpansion("time", {"0", "to", "1h30m", "by", "30m"}, {"0000", "0030", "0100", "0130"}); } //----------------------------------------------------------------------------- } // namespace metkit::mars::test int main(int argc, char** argv) { return eckit::testing::run_tests(argc, argv); } metkit-1.16.0/tests/test_type_levelist.cc000066400000000000000000000061601513171467200205060ustar00rootroot00000000000000/* * (C) Copyright 1996- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ /// @file test_levelist.cc /// @author Metin Cakircali /// @author Emanuele Danovaro /// @date November 2023 #include #include #include #include "eckit/testing/Test.h" #include "metkit/mars/MarsLanguage.h" #include "metkit/mars/Type.h" #include "metkit/mars/TypesFactory.h" namespace metkit::mars::test { //----------------------------------------------------------------------------- CASE("test_metkit_exists_to-by-list-float") { std::stringstream ss; TypesFactory::list(ss); const std::string str(ss.str()); EXPECT(str.find_first_of("to-by-list-float")); } void assertTypeExpansion(const std::string& name, std::vector values, const std::vector& expected) { static MarsLanguage language("retrieve"); language.type(name)->expand(values); EXPECT_EQUAL(values, expected); } CASE("test_metkit_expand_levelist") { // by > 0 assertTypeExpansion("levelist", {"-1", "to", "2", "by", "0.5"}, {"-1", "-0.5", "0", ".5", "1", "1.5", "2"}); // by > 0 assertTypeExpansion("levelist", {"-10.0", "to", "2.0", "by", "1"}, {"-10", "-9", "-8", "-7", "-6", "-5", "-4", "-3", "-2", "-1", "0", "1", "2"}); // by > 0 && from < to assertTypeExpansion("levelist", {"4", "to", "20", "by", "4"}, {"4", "8", "12", "16", "20"}); assertTypeExpansion("levelist", {"4", "to", "18", "by", "4"}, {"4", "8", "12", "16"}); // by > 0 && from > to assertTypeExpansion("levelist", {"20", "to", "4", "by", "4"}, {"20", "16", "12", "8", "4"}); // by = 0 EXPECT_THROWS_AS(assertTypeExpansion("levelist", {"4", "to", "20", "by", "0"}, {"4"}), eckit::BadValue); EXPECT_THROWS_AS(assertTypeExpansion("levelist", {"-1", "to", "2", "by", "0"}, {"-1"}), eckit::BadValue); // by < 0 && from > to assertTypeExpansion("levelist", {"20", "to", "4", "by", "-4"}, {"20", "16", "12", "8", "4"}); assertTypeExpansion("levelist", {"10", "to", "4", "by", "-2"}, {"10", "8", "6", "4"}); assertTypeExpansion("levelist", {"-2", "to", "-4", "by", "-0.5"}, {"-2", "-2.5", "-3", "-3.5", "-4"}); assertTypeExpansion("levelist", {"0", "to", "-2", "by", "-0.5"}, {"0", "-0.5", "-1", "-1.5", "-2"}); // by < 0 && from < to EXPECT_THROWS_AS(assertTypeExpansion("levelist", {"4", "to", "10", "by", "-4"}, {"4", "8", "12", "16", "20"}), eckit::BadValue); EXPECT_THROWS_AS( assertTypeExpansion("levelist", {"-4", "to", "2", "by", "-0.5"}, {"0", "-0.5", "-1", "-1.5", "-2"}), eckit::BadValue); } } // namespace metkit::mars::test //----------------------------------------------------------------------------- int main(int argc, char** argv) { return eckit::testing::run_tests(argc, argv); } metkit-1.16.0/tests/test_typesfactory.cc000066400000000000000000000032301513171467200203450ustar00rootroot00000000000000/* * (C) Copyright 1996- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * In applying this licence, ECMWF does not waive the privileges and immunities * granted to it by virtue of its status as an intergovernmental organisation nor * does it submit to any jurisdiction. */ /// @file test_typesfactory.cc /// @author Simon Smart /// @date April 2017 #include #include #include #include "eckit/testing/Test.h" #include "eckit/value/Value.h" #include "metkit/mars/TypeDate.h" #include "metkit/mars/TypesFactory.h" namespace metkit::mars::test { //----------------------------------------------------------------------------- CASE("test_list_types") { std::stringstream ss; TypesFactory::list(ss); std::cout << ss.str() << std::endl; EXPECT(ss.str() == std::string("[any,date,enum,expver,float,integer,lowercase,mixed,param,range,regex,time,to-by-" "list,to-by-list-float,to-by-list-quantile]")); } CASE("test_build") { eckit::ValueMap settings; settings["type"] = "date"; Type* t1(TypesFactory::build("abcd", eckit::Value(settings))); EXPECT(t1 != 0); t1->attach(); // Check that we have obtained the correct type EXPECT(dynamic_cast(t1) != 0); // Clean up, taking into account that ~Type is protected. t1->detach(); } } // namespace metkit::mars::test //----------------------------------------------------------------------------- int main(int argc, char** argv) { return eckit::testing::run_tests(argc, argv); }